This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3065. LWG 2989 missed that all `path`'s other operators should be hidden friends as well

Section: 31.12.6.8 [fs.path.nonmember] Status: C++20 Submitter: Billy O'Neal III Opened: 2018-02-13 Last modified: 2021-02-25

Priority: 2

View all issues with C++20 status.

Discussion:

Consider the following program:

>     // See godbolt link
>     #include <assert.h>
>     #include <string>
>     #include <filesystem>

>     using namespace std;
>     using namespace std::filesystem;

>     int main() {
>       bool b = L"a//b" == std::string("a/b");
>       assert(b); // passes. What?!
>       return b;
>     }

`L"a"` gets converted into a `path`, and the string gets converted into a `path`, and then those paths are compared for equality. But `path` equality comparison doesn't work anything like string equality comparison, leading to surprises.

`path`'s other operators should be made hidden friends as well, so that one side or the other of a given operator is of type `path` before those conversions apply.

[2018-02-20, Priority set to 2 after mailing list discussion]

[2018-08-23 Batavia Issues processing]

Status to Tentatively Ready

[2018-11, Adopted in San Diego]

Proposed resolution:

This wording is relative to N4713.

All drafting notes from LWG 2989 apply here too.

1. Modify 31.12.4 [fs.filesystem.syn], header `<filesystem>` synopsis, as indicated:

   >     […]
   >     // 31.12.6.8 [fs.path.nonmember], path non-member functions
   >     void swap(path& lhs, path& rhs) noexcept;
   >     size_t hash_value(const path& p) noexcept;

   >     bool operator==(const path& lhs, const path& rhs) noexcept;
   >     bool operator!=(const path& lhs, const path& rhs) noexcept;
   >     bool operator< (const path& lhs, const path& rhs) noexcept;
   >     bool operator<=(const path& lhs, const path& rhs) noexcept;
   >     bool operator> (const path& lhs, const path& rhs) noexcept;
   >     bool operator>=(const path& lhs, const path& rhs) noexcept;

   >     path operator/ (const path& lhs, const path& rhs);
   >     […]

2. Modify 31.12.6.8 [fs.path.nonmember] as indicated:

   >     […]
   >     friend bool operator< (const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend bool operator<=(const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend bool operator> (const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend bool operator>=(const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend bool operator==(const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend bool operator!=(const path& lhs, const path& rhs) noexcept;
   >     […]
   >     friend path operator/ (const path& lhs, const path& rhs);
   >     […]

3. Modify 31.12.6 [fs.class.path], class `path` synopsis, as indicated:

   >     class path {
   >     public:
   >       […]
   >       // 31.12.6.5.5 [fs.path.modifiers], modifiers
   >       […]

   >       // 31.12.6.8 [fs.path.nonmember], non-member operators
   >       friend bool operator< (const path& lhs, const path& rhs) noexcept;
   >       friend bool operator<=(const path& lhs, const path& rhs) noexcept;
   >       friend bool operator> (const path& lhs, const path& rhs) noexcept;
   >       friend bool operator>=(const path& lhs, const path& rhs) noexcept;
   >       friend bool operator==(const path& lhs, const path& rhs) noexcept;
   >       friend bool operator!=(const path& lhs, const path& rhs) noexcept;

   >       friend path operator/ (const path& lhs, const path& rhs);

   >       // 31.12.6.5.6 [fs.path.native.obs], native format observers
   >       […]
   >     };