Section: 31.12.6.5.8 [fs.path.compare] Status: C++20 Submitter: Billy Robert O'Neal III Opened: 2017-02-21 Last modified: 2021-02-25
Priority: 2
View all issues with C++20 status.
Discussion:
Currently, path comparison is defined elementwise, which implies a conversion from the native format (implied by
native()
returning const string&
). However, the conversion from the native format to the generic
format might not be information preserving. This would allow two paths a
and b
to say
a.compare(b) == 0
, but a.native().compare(b.native()) != 0
as a result of this missing information,
which is undesirable. We only want that condition to happen if there are redundant directory separators. We also don't
want to change the path comparison to be in terms of the native format, due to Peter Dimov's example where we want
path("a/b")
to sort earlier than path("a.b")
, and we want path("a/b") == path("a//////b")
.
path("a/b:ads") == path("a/b")
. I think I should consider the alternate data streams as part of the path
element though, so this case might be fine, so long as I make path("b:ads").native()
be "b:ads"
.
This might not work for our z/OS friends though, or for folks where the native format looks nothing like the generic format.
Additionally, this treats root-directory specially. For example, the current spec wants path("c:/a/b") == path("c:/a////b")
,
but path("c:/a/b") != path("c:///a/b")
, because native()
for the root-directory path element will literally
be the slashes or preferred separators.
This addresses similar issues to those raised in US 57 — it won't make absolute paths sort at the beginning or end
but it will make paths of the same kind sort together.
[2017-03-04, Kona Saturday morning]
We decided that this had seen so much churn that we would postpone looking at this until Toronto
[2017-07 Toronto Thurs Issue Prioritization]
Priority 2
[2016-07, Toronto Saturday afternoon issues processing]
Billy to reword after Davis researches history about ordering. Status to Open.
Previous resolution [SUPERSEDED]:
This wording is relative to N4640.
Make the following edits to 31.12.6.5.8 [fs.path.compare]:
int compare(const path& p) const noexcept;-1- Returns:
— Let
rootNameComparison
be the result ofthis->root_name().native().compare(p.root_name().native())
. IfrootNameComparison
is not0
,rootNameComparison
; otherwise,— If
this->has_root_directory()
and!p.has_root_directory()
, a value less than0
; otherwise,— If
!this->has_root_directory()
andp.has_root_directory()
, a value greater than0
; otherwise,— A value greater than, less than, or equal to 0, ordering the paths in a depth-first traversal order.
-?- [Note: For POSIX and Windows platforms, this is accomplished by lexicographically ordering the half-open ranges
[begin(), end())
ofthis->relative_path()
andp.relative_path()
as follows:— A value less than
0
, ifnative()
for the elements ofare lexicographically less than
*this->relative_path()native()
for the elements ofp.relative_path()
; otherwise,— a value greater than
0
, ifnative()
for the elements ofare lexicographically greater than
*this->relative_path()native()
for the elements ofp.relative_path()
; otherwise,—
0
.— end note]
-2- Remarks: The elements are determined as if by iteration over the half-open range[begin(), end())
for*this
andp
.int compare(const string_type& s) const int compare(basic_string_view<value_type> s) const;
-3- Returns:compare(path(s))
[Editor's note: Delete paragraph 3 entirely and merge the
value_type
overload with those above.]int compare(const value_type* s) const-4-
ReturnsEffects: Equivalent toreturn
compare(path(s));
.
[2018-01-26 issues processing telecon]
Status set to 'Review'. We like the wording, but would like to see some implementation experience.
Previous resolution [SUPERSEDED]:
This wording is relative to N4659.
Make the following edits to 31.12.6.5.8 [fs.path.compare]:
int compare(const path& p) const noexcept;-1- Returns:
— Let
rootNameComparison
be the result ofthis->root_name().native().compare(p.root_name().native())
. IfrootNameComparison
is not0
,rootNameComparison
; otherwise,— If
this->has_root_directory()
and!p.has_root_directory()
, a value less than0
; otherwise,— If
!this->has_root_directory()
andp.has_root_directory()
, a value greater than0
; otherwise,—
a value less thanIf0
, inative()
for the elements ofare lexicographically less than
*this->relative_path()native()
for the elements ofp.relative_path()
, a value less than0
; otherwise,—
a value greater thanIf0
, inative()
for the elements ofare lexicographically greater than
*this->relative_path()native()
for the elements ofp.relative_path()
, a value greater than0
; otherwise,—
0
.
-2- Remarks: The elements are determined as if by iteration over the half-open range[begin(), end())
for*this
andp
.int compare(const string_type& s) const int compare(basic_string_view<value_type> s) const;
-3- Returns:compare(path(s))
[Editor's note: Delete paragraph 3 entirely and merge the
value_type
overload with those above.]int compare(const value_type* s) const-4-
ReturnsEffects: Equivalent toreturn
compare(path(s));
.
[2018-02-13 Billy improves wording]
The revised wording has the effect to invert the ordering of the added new bullets (2) and (3), the effect of this change is that
path("c:/").compare("c:")
compares greater, not less.
[2018-06, Rapperswil Wednesday evening]
Agreement to move that to Ready, Daniel rebased to N4750.
[2018-11, Adopted in San Diego]
Proposed resolution:
This wording is relative to N4750.
Make the following edits to 31.12.6.5.8 [fs.path.compare]:
int compare(const path& p) const noexcept;-1- Returns:
— Let
rootNameComparison
be the result ofthis->root_name().native().compare(p.root_name().native())
. IfrootNameComparison
is not0
,rootNameComparison
; otherwise,— If
!this->has_root_directory()
andp.has_root_directory()
, a value less than0
; otherwise,— If
this->has_root_directory()
and!p.has_root_directory()
, a value greater than0
; otherwise,—
a value less thanIf0
, inative()
for the elements ofare lexicographically less than
*this->relative_path()native()
for the elements ofp.relative_path()
, a value less than0
; otherwise,—
a value greater thanIf0
, inative()
for the elements ofare lexicographically greater than
*this->relative_path()native()
for the elements ofp.relative_path()
, a value greater than0
; otherwise,—
0
.
-2- Remarks: The elements are determined as if by iteration over the half-open range[begin(), end())
for*this
andp
.int compare(const string_type& s) const int compare(basic_string_view<value_type> s) const;
-3- Returns:compare(path(s))
[Editor's note: Delete paragraph 3 entirely and merge the
value_type
overload with those above.]int compare(const value_type* s) const-4-
ReturnsEffects: Equivalent to:return
compare(path(s));
.