diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -75,7 +75,7 @@ | chrono::leap_second | chrono::time_zone_link",A ```` implementation,Unassigned,|Not Started| | `[fs.filesystem.syn] `_,| `filesystem::space_info `_,None,Adrian Vogelsgesang,|Complete| -| `[fs.path.nonmember] `_,| `filesystem::path `_,None,Adrian Vogelsgesang,|In Progress| +| `[fs.path.nonmember] `_,| `filesystem::path `_,None,Adrian Vogelsgesang,|Complete| | `[fs.dir.entry.obs] `_,| `filesystem::directory_entry `_,None,Adrian Vogelsgesang,|In Progress| | `[re.submatch.op] `_,| sub_match,None,Mark de Wever,|In Progress| | `[thread.thread.id] `_,| `thread::id `_,None,Adrian Vogelsgesang,|Complete| diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -732,6 +732,37 @@ path& replace_extension(const path& __replacement = path()); + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) == 0; + } +# if _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) != 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) < 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) <= 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) > 0; + } + friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) >= 0; + } +# else // _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.__compare(__rhs.__pn_) <=> 0; + } +# endif // _LIBCPP_STD_VER <= 17 + + friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) { + path __result(__lhs); + __result /= __rhs; + return __result; + } + _LIBCPP_HIDE_FROM_ABI void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } @@ -1035,30 +1066,6 @@ } #endif // !_LIBCPP_HAS_NO_LOCALIZATION - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) == 0; - } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) != 0; - } - friend _LIBCPP_HIDE_FROM_ABI bool operator<(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) < 0; - } - friend _LIBCPP_HIDE_FROM_ABI bool operator<=(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) <= 0; - } - friend _LIBCPP_HIDE_FROM_ABI bool operator>(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) > 0; - } - friend _LIBCPP_HIDE_FROM_ABI bool operator>=(const path& __lhs, const path& __rhs) noexcept { - return __lhs.__compare(__rhs.__pn_) >= 0; - } - - friend _LIBCPP_HIDE_FROM_ABI path operator/(const path& __lhs, const path& __rhs) { - path __result(__lhs); - __result /= __rhs; - return __result; - } private: inline _LIBCPP_HIDE_FROM_ABI path& __assign_view(__string_view const& __s) noexcept { diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem --- a/libcxx/include/filesystem +++ b/libcxx/include/filesystem @@ -14,29 +14,150 @@ namespace std::filesystem { - class path; + // `class path` from http://eel.is/c++draft/fs.class.path.general#6 + class path { + public: + using value_type = see below; + using string_type = basic_string; + static constexpr value_type preferred_separator = see below; + + enum format; + + path() noexcept; + path(const path& p); + path(path&& p) noexcept; + path(string_type&& source, format fmt = auto_format); + template + path(const Source& source, format fmt = auto_format); + template + path(InputIterator first, InputIterator last, format fmt = auto_format); + template + path(const Source& source, const locale& loc, format fmt = auto_format); + template + path(InputIterator first, InputIterator last, const locale& loc, format fmt = auto_format); + ~path(); + + path& operator=(const path& p); + path& operator=(path&& p) noexcept; + path& operator=(string_type&& source); + path& assign(string_type&& source); + template + path& operator=(const Source& source); + template + path& assign(const Source& source); + template + path& assign(InputIterator first, InputIterator last); + + path& operator/=(const path& p); + template + path& operator/=(const Source& source); + template + path& append(const Source& source); + template + path& append(InputIterator first, InputIterator last); + + path& operator+=(const path& x); + path& operator+=(const string_type& x); + path& operator+=(basic_string_view x); + path& operator+=(const value_type* x); + path& operator+=(value_type x); + template + path& operator+=(const Source& x); + template + path& operator+=(EcharT x); + template + path& concat(const Source& x); + template + path& concat(InputIterator first, InputIterator last); + + void clear() noexcept; + path& make_preferred(); + path& remove_filename(); + path& replace_filename(const path& replacement); + path& replace_extension(const path& replacement = path()); + void swap(path& rhs) noexcept; + + friend bool operator==(const path& lhs, const path& rhs) noexcept; + friend bool operator!=(const path& lhs, const path& rhs) noexcept; // removed in C++20 + friend bool operator< (const path& lhs, const path& rhs) noexcept; // removed in C++20 + friend bool operator<=(const path& lhs, const path& rhs) noexcept; // removed in C++20 + friend bool operator> (const path& lhs, const path& rhs) noexcept; // removed in C++20 + friend bool operator>=(const path& lhs, const path& rhs) noexcept; // removed in C++20 + friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; // C++20 + + friend path operator/(const path& lhs, const path& rhs); + + const string_type& native() const noexcept; + const value_type* c_str() const noexcept; + operator string_type() const; + + template, + class Allocator = allocator> + basic_string + string(const Allocator& a = Allocator()) const; + std::string string() const; + std::wstring wstring() const; + std::u8string u8string() const; + std::u16string u16string() const; + std::u32string u32string() const; + + template, + class Allocator = allocator> + basic_string + generic_string(const Allocator& a = Allocator()) const; + std::string generic_string() const; + std::wstring generic_wstring() const; + std::u8string generic_u8string() const; + std::u16string generic_u16string() const; + std::u32string generic_u32string() const; + + int compare(const path& p) const noexcept; + int compare(const string_type& s) const; + int compare(basic_string_view s) const; + int compare(const value_type* s) const; + + path root_name() const; + path root_directory() const; + path root_path() const; + path relative_path() const; + path parent_path() const; + path filename() const; + path stem() const; + path extension() const; + + [[nodiscard]] bool empty() const noexcept; + bool has_root_name() const; + bool has_root_directory() const; + bool has_root_path() const; + bool has_relative_path() const; + bool has_parent_path() const; + bool has_filename() const; + bool has_stem() const; + bool has_extension() const; + bool is_absolute() const; + bool is_relative() const; + + path lexically_normal() const; + path lexically_relative(const path& base) const; + path lexically_proximate(const path& base) const; + + class iterator; + using const_iterator = iterator; + + iterator begin() const; + iterator end() const; + + template + friend basic_ostream& + operator<<(basic_ostream& os, const path& p); + template + friend basic_istream& + operator>>(basic_istream& is, path& p); + }; 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); - - // fs.path.io operators are friends of path. - template - friend basic_ostream& - operator<<(basic_ostream& os, const path& p); - - template - friend basic_istream& - operator>>(basic_istream& is, path& p); - template path u8path(const Source& source); template diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp @@ -22,16 +22,17 @@ // bool operator<=(path const&, path const&) noexcept; // bool operator> (path const&, path const&) noexcept; // bool operator>=(path const&, path const&) noexcept; +// strong_ordering operator<=>(path const&, path const&) noexcept; // // size_t hash_value(path const&) noexcept; - #include "filesystem_include.h" #include #include #include #include "test_macros.h" +#include "test_comparisons.h" #include "test_iterators.h" #include "count_new.h" #include "filesystem_test_helper.h" @@ -111,21 +112,19 @@ { // comparison operators DisableAllocationGuard g; // none of these operations should allocate - // Check runtime result - assert((p1 == p2) == (E == 0)); - assert((p1 != p2) == (E != 0)); - assert((p1 < p2) == (E < 0)); - assert((p1 <= p2) == (E <= 0)); - assert((p1 > p2) == (E > 0)); - assert((p1 >= p2) == (E >= 0)); - - // Check signatures - ASSERT_NOEXCEPT(p1 == p2); - ASSERT_NOEXCEPT(p1 != p2); - ASSERT_NOEXCEPT(p1 < p2); - ASSERT_NOEXCEPT(p1 <= p2); - ASSERT_NOEXCEPT(p1 > p2); - ASSERT_NOEXCEPT(p1 >= p2); + // check signatures + AssertComparisonsAreNoexcept(); + AssertComparisonsReturnBool(); +#if TEST_STD_VER > 17 + AssertOrderAreNoexcept(); + AssertOrderReturn(); +#endif + + // check comarison results + assert(testComparisons(p1, p2, /*isEqual*/ E == 0, /*isLess*/ E < 0)); +#if TEST_STD_VER > 17 + assert(testOrder(p1, p2, E <=> 0)); +#endif } { // check hash values auto h1 = hash_value(p1);