[libcxx-commits] [libcxx] b3ab3be - [libc++] Implement `operator<=>` for `filesystem::path`
Adrian Vogelsgesang via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 18 14:14:05 PDT 2022
Author: Adrian Vogelsgesang
Date: 2022-08-18T14:13:48-07:00
New Revision: b3ab3bece0bf1d441518b7d3b1294cb72445cb0f
URL: https://github.com/llvm/llvm-project/commit/b3ab3bece0bf1d441518b7d3b1294cb72445cb0f
DIFF: https://github.com/llvm/llvm-project/commit/b3ab3bece0bf1d441518b7d3b1294cb72445cb0f.diff
LOG: [libc++] Implement `operator<=>` for `filesystem::path`
Implements part of P1614R2 "The Mothership has Landed"
Differential Revision: https://reviews.llvm.org/D130859
Added:
Modified:
libcxx/docs/Status/SpaceshipProjects.csv
libcxx/include/__filesystem/path.h
libcxx/include/filesystem
libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 5b4e52c228af5..6f3ea312e99b7 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -75,7 +75,7 @@ Section,Description,Dependencies,Assignee,Complete
| chrono::leap_second
| chrono::time_zone_link",A ``<chrono>`` implementation,Unassigned,|Not Started|
| `[fs.filesystem.syn] <https://wg21.link/fs.filesystem.syn>`_,| `filesystem::space_info <https://reviews.llvm.org/D130861>`_,None,Adrian Vogelsgesang,|Complete|
-| `[fs.path.nonmember] <https://wg21.link/fs.path.nonmember>`_,| `filesystem::path <https://reviews.llvm.org/D130859>`_,None,Adrian Vogelsgesang,|In Progress|
+| `[fs.path.nonmember] <https://wg21.link/fs.path.nonmember>`_,| `filesystem::path <https://reviews.llvm.org/D130859>`_,None,Adrian Vogelsgesang,|Complete|
| `[fs.dir.entry.obs] <https://wg21.link/fs.dir.entry.obs>`_,| `filesystem::directory_entry <https://reviews.llvm.org/D130860>`_,None,Adrian Vogelsgesang,|In Progress|
| `[re.submatch.op] <https://wg21.link/re.submatch.op>`_,| sub_match,None,Mark de Wever,|In Progress|
| `[thread.thread.id] <https://wg21.link/thread.thread.id>`_,| `thread::id <https://reviews.llvm.org/D131362>`_,None,Adrian Vogelsgesang,|Complete|
diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h
index 8fafd72c7e4f6..6307b594a888f 100644
--- a/libcxx/include/__filesystem/path.h
+++ b/libcxx/include/__filesystem/path.h
@@ -732,6 +732,37 @@ class _LIBCPP_TYPE_VIS path {
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 @@ class _LIBCPP_TYPE_VIS path {
}
#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
index aa0cd562e2afb..8b81e10515a6e 100644
--- 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<value_type>;
+ 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<class Source>
+ path(const Source& source, format fmt = auto_format);
+ template<class InputIterator>
+ path(InputIterator first, InputIterator last, format fmt = auto_format);
+ template<class Source>
+ path(const Source& source, const locale& loc, format fmt = auto_format);
+ template<class InputIterator>
+ 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<class Source>
+ path& operator=(const Source& source);
+ template<class Source>
+ path& assign(const Source& source);
+ template<class InputIterator>
+ path& assign(InputIterator first, InputIterator last);
+
+ path& operator/=(const path& p);
+ template<class Source>
+ path& operator/=(const Source& source);
+ template<class Source>
+ path& append(const Source& source);
+ template<class InputIterator>
+ path& append(InputIterator first, InputIterator last);
+
+ path& operator+=(const path& x);
+ path& operator+=(const string_type& x);
+ path& operator+=(basic_string_view<value_type> x);
+ path& operator+=(const value_type* x);
+ path& operator+=(value_type x);
+ template<class Source>
+ path& operator+=(const Source& x);
+ template<class EcharT>
+ path& operator+=(EcharT x);
+ template<class Source>
+ path& concat(const Source& x);
+ template<class InputIterator>
+ 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 EcharT, class traits = char_traits<EcharT>,
+ class Allocator = allocator<EcharT>>
+ basic_string<EcharT, traits, Allocator>
+ 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 EcharT, class traits = char_traits<EcharT>,
+ class Allocator = allocator<EcharT>>
+ basic_string<EcharT, traits, Allocator>
+ 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<value_type> 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<class charT, class traits>
+ friend basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& os, const path& p);
+ template<class charT, class traits>
+ friend basic_istream<charT, traits>&
+ operator>>(basic_istream<charT, traits>& 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 <class charT, class traits>
- friend basic_ostream<charT, traits>&
- operator<<(basic_ostream<charT, traits>& os, const path& p);
-
- template <class charT, class traits>
- friend basic_istream<charT, traits>&
- operator>>(basic_istream<charT, traits>& is, path& p);
-
template <class Source>
path u8path(const Source& source);
template <class InputIterator>
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
index 975e96c3031cf..3e194a7816132 100644
--- 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 <type_traits>
#include <vector>
#include <cassert>
#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 @@ void test_compare_basic()
{ // 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<path>();
+ AssertComparisonsReturnBool<path>();
+#if TEST_STD_VER > 17
+ AssertOrderAreNoexcept<path>();
+ AssertOrderReturn<std::strong_ordering, path>();
+#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);
More information about the libcxx-commits
mailing list