diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -36,6 +36,7 @@ _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } +#if _LIBCPP_STD_VER < 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { return __x.__ptr_ == __y.__ptr_; } @@ -43,6 +44,9 @@ friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { return !(__x == __y); } +#else + bool operator==(const exception_ptr&) const = default; +#endif friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h --- a/libcxx/include/__expected/unexpected.h +++ b/libcxx/include/__expected/unexpected.h @@ -108,6 +108,8 @@ return __x.__unex_ == __y.__unex_; } + bool operator==(const unexpected&) const requires is_object_v<_Err> = default; + private: _Err __unex_; }; diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h --- a/libcxx/include/__iterator/wrap_iter.h +++ b/libcxx/include/__iterator/wrap_iter.h @@ -150,6 +150,11 @@ template friend class basic_string; template friend class _LIBCPP_TEMPLATE_VIS vector; template friend class _LIBCPP_TEMPLATE_VIS span; + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const __wrap_iter&) const = default; +#endif }; template diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -578,6 +578,11 @@ tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, __tuple_indices<_I1...>, __tuple_indices<_I2...>); #endif + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const pair&) const requires (is_object_v<_T1> && is_object_v<_T2>) = default; +#endif }; #if _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/array b/libcxx/include/array --- a/libcxx/include/array +++ b/libcxx/include/array @@ -256,6 +256,11 @@ value_type* data() _NOEXCEPT {return __elems_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 const value_type* data() const _NOEXCEPT {return __elems_;} + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const array&) const = default; +#endif }; template @@ -382,6 +387,11 @@ _LIBCPP_ASSERT(false, "cannot call array::back() on a zero-sized array"); __libcpp_unreachable(); } + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const array&) const = default; +#endif }; diff --git a/libcxx/include/complex b/libcxx/include/complex --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -310,6 +310,11 @@ *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const complex&) const = default; +#endif }; template<> class _LIBCPP_TEMPLATE_VIS complex; diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -382,6 +382,7 @@ return __t; } +#if _LIBCPP_STD_VER <= 20 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __forward_list_iterator& __x, const __forward_list_iterator& __y) @@ -390,6 +391,10 @@ bool operator!=(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {return !(__x == __y);} +#else +public: + bool operator==(const __forward_list_iterator&) const = default; +#endif }; template @@ -466,6 +471,7 @@ return __t; } +#if _LIBCPP_STD_VER <= 20 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) @@ -474,6 +480,10 @@ bool operator!=(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) {return !(__x == __y);} +#else +public: + bool operator==(const __forward_list_const_iterator&) const = default; +#endif }; template diff --git a/libcxx/include/list b/libcxx/include/list --- a/libcxx/include/list +++ b/libcxx/include/list @@ -420,6 +420,7 @@ _LIBCPP_INLINE_VISIBILITY __list_iterator operator--(int) {__list_iterator __t(*this); --(*this); return __t;} +#if _LIBCPP_STD_VER <= 20 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __list_iterator& __x, const __list_iterator& __y) { @@ -428,6 +429,10 @@ friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __list_iterator& __x, const __list_iterator& __y) {return !(__x == __y);} +#else +public: + bool operator==(const __list_iterator&) const = default; +#endif }; template @@ -535,6 +540,7 @@ _LIBCPP_INLINE_VISIBILITY __list_const_iterator operator--(int) {__list_const_iterator __t(*this); --(*this); return __t;} +#if _LIBCPP_STD_VER <= 20 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __list_const_iterator& __x, const __list_const_iterator& __y) { @@ -543,6 +549,10 @@ friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __list_const_iterator& __x, const __list_const_iterator& __y) {return !(__x == __y);} +#else +public: + bool operator==(const __list_const_iterator&) const = default; +#endif }; template diff --git a/libcxx/include/tuple b/libcxx/include/tuple --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1310,6 +1310,11 @@ __base_.swap(__t.__base_); } #endif // _LIBCPP_STD_VER >= 23 + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const tuple&) const requires (__all...>::value) = default; +#endif }; template <> @@ -1334,6 +1339,11 @@ #if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void swap(const tuple&) const noexcept {} #endif + +#if _LIBCPP_STD_VER >= 20 +public: + bool operator==(const tuple&) const = default; +#endif }; #if _LIBCPP_STD_VER >= 23 diff --git a/libcxx/test/libcxx/types_are_trivially_equality_comparable.compile.pass.cpp b/libcxx/test/libcxx/types_are_trivially_equality_comparable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/types_are_trivially_equality_comparable.compile.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: clang +// UNSUPPORTED: clang-15, clang-16 +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// ADDITIONAL_COMPILE_FLAGS: -Wno-private-header + +#include <__iterator/wrap_iter.h> +#include <__type_traits/is_equality_comparable.h> + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool is_tec = std::__libcpp_is_trivially_equality_comparable::value; + +static_assert(is_tec>); +static_assert(is_tec>); +static_assert(is_tec::iterator>); +static_assert(is_tec::const_iterator>); +static_assert(is_tec::iterator>); +static_assert(is_tec::const_iterator>); +// These are currently false because of a compiler bug +// static_assert(is_tec>); +// static_assert(is_tec>); +// static_assert(is_tec>); +static_assert(is_tec>); + +#if TEST_STD_VER >= 23 +static_assert(is_tec>); +#endif + +// TODO: Make these types trivially equality comparable: +// - std::chrono types +// - std::coroutine_handle +// - std::filesystem::space_info +// - std::unique_ptr +// - iterator_t +// - iterator_t +// - iterator_t +// - error_code +// - error_condition +// - set, map, unordered_set, etc. iterators