diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 358889d8dbc37..fe24b523bb98e 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -202,7 +202,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_common_reference_wrapper`` ``202302L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_concepts`` ``202002L`` + ``__cpp_lib_concepts`` ``202207L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` ---------------------------------------------------------- ----------------- diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index db918a16e9a61..48288e3748ae3 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -305,6 +305,7 @@ set(files __concepts/class_or_enum.h __concepts/common_reference_with.h __concepts/common_with.h + __concepts/comparison_common_type.h __concepts/constructible.h __concepts/convertible_to.h __concepts/copyable.h diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h index 7a44ea9158a6f..ad6d05a681145 100644 --- a/libcxx/include/__compare/three_way_comparable.h +++ b/libcxx/include/__compare/three_way_comparable.h @@ -12,6 +12,7 @@ #include <__compare/common_comparison_category.h> #include <__compare/ordering.h> #include <__concepts/common_reference_with.h> +#include <__concepts/comparison_common_type.h> #include <__concepts/equality_comparable.h> #include <__concepts/same_as.h> #include <__concepts/totally_ordered.h> @@ -39,8 +40,7 @@ concept three_way_comparable = template concept three_way_comparable_with = - three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && __comparison_common_type_with<_Tp, _Up> && three_way_comparable, __make_const_lvalue_ref<_Up>>, _Cat> && __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> && requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h new file mode 100644 index 0000000000000..3f0d770511f47 --- /dev/null +++ b/libcxx/include/__concepts/comparison_common_type.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H +#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H + +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__type_traits/common_reference.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template > +concept __comparison_common_type_with_impl = + same_as, common_reference_t> && requires { + requires convertible_to || convertible_to<_Tp, const _CommonRef&>; + requires convertible_to || convertible_to<_Up, const _CommonRef&>; + }; + +template +concept __comparison_common_type_with = __comparison_common_type_with_impl, remove_cvref_t<_Up>>; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h index 278fc76409289..56fc6f8b685c0 100644 --- a/libcxx/include/__concepts/equality_comparable.h +++ b/libcxx/include/__concepts/equality_comparable.h @@ -11,6 +11,7 @@ #include <__concepts/boolean_testable.h> #include <__concepts/common_reference_with.h> +#include <__concepts/comparison_common_type.h> #include <__config> #include <__type_traits/common_reference.h> #include <__type_traits/make_const_lvalue_ref.h> @@ -41,7 +42,7 @@ concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; template concept equality_comparable_with = equality_comparable<_Tp> && equality_comparable<_Up> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + __comparison_common_type_with<_Tp, _Up> && equality_comparable< common_reference_t< __make_const_lvalue_ref<_Tp>, diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 63cf8e847751f..23a59f8abb1d6 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1069,6 +1069,7 @@ module std [system] { module class_or_enum { header "__concepts/class_or_enum.h" } module common_reference_with { header "__concepts/common_reference_with.h" } module common_with { header "__concepts/common_with.h" } + module comparison_common_type { header "__concepts/comparison_common_type.h" } module constructible { header "__concepts/constructible.h" } module convertible_to { header "__concepts/convertible_to.h" } module copyable { header "__concepts/copyable.h" } diff --git a/libcxx/include/version b/libcxx/include/version index 16917a3bd9ddd..f0bfb94682c91 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -62,7 +62,7 @@ __cpp_lib_clamp 201603L __cpp_lib_common_reference 202302L __cpp_lib_common_reference_wrapper 202302L __cpp_lib_complex_udls 201309L -__cpp_lib_concepts 202002L +__cpp_lib_concepts 202207L __cpp_lib_constexpr_algorithms 202306L 201806L // C++20 __cpp_lib_constexpr_bitset 202207L @@ -406,7 +406,7 @@ __cpp_lib_void_t 201411L # endif # define __cpp_lib_common_reference 202302L # define __cpp_lib_common_reference_wrapper 202302L -# define __cpp_lib_concepts 202002L +# define __cpp_lib_concepts 202207L # define __cpp_lib_constexpr_algorithms 201806L # define __cpp_lib_constexpr_complex 201711L # define __cpp_lib_constexpr_dynamic_alloc 201907L diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp index 532ee9b03efc0..36ec7892faa22 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp @@ -75,7 +75,12 @@ static_assert(!HasPartialSortCopyIter); // !indirectly_copyable -static_assert(!HasPartialSortCopyIter); +struct OrderedConvertibleToInt { + friend auto operator<=>(OrderedConvertibleToInt const&, OrderedConvertibleToInt const&) = default; + operator int() const; +}; + +static_assert(!HasPartialSortCopyIter); // !sortable static_assert(!HasPartialSortCopyIter); @@ -84,6 +89,9 @@ struct NoComparator {}; // !indirect_strict_weak_order, projected> static_assert(!HasPartialSortCopyIter); +// P2404 +static_assert(HasPartialSortCopyIter); + // Test constraints of the (range) overload. // ====================================================== @@ -109,7 +117,7 @@ static_assert(!HasPartialSortCopyRange, RandomAccessRangeNotDerivedFrom> static_assert(!HasPartialSortCopyRange, RandomAccessRangeBadIndex>); // !indirectly_copyable, iterator_t> -static_assert(!HasPartialSortCopyRange, R>); +static_assert(!HasPartialSortCopyRange, R>); // !sortable, Comp, Proj2> static_assert(!HasPartialSortCopyRange, R>); @@ -117,6 +125,9 @@ static_assert(!HasPartialSortCopyRange, R>); // !indirect_strict_weak_order, Proj1>, projected, Proj2>> static_assert(!HasPartialSortCopyRange, R>); +// P2404 +static_assert(HasPartialSortCopyRange, R>); + static_assert(std::is_same_v, std::ranges::in_out_result>); template diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp index 2f8d7862c0f4d..cfe4679fba533 100644 --- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp @@ -1131,4 +1131,9 @@ static_assert( std::common_reference_with); static_assert( !check_equality_comparable_with()); + +// P2404 +static_assert(check_equality_comparable_with()); +static_assert(check_equality_comparable_with, std::nullptr_t>()); +static_assert(!check_equality_comparable_with()); } // namespace types_fit_for_purpose diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp index aa2ab1c0e9ef1..01dfc2a27cfca 100644 --- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp +++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp @@ -15,6 +15,7 @@ #include #include "compare_types.h" +#include "test_macros.h" template constexpr bool check_three_way_comparable_with() { @@ -224,4 +225,28 @@ struct SpaceshipNonConstArgument { }; static_assert(!check_three_way_comparable_with()); + +struct MoveOnlyIntComparable { + MoveOnlyIntComparable(int) {} + + MoveOnlyIntComparable(MoveOnlyIntComparable&&) = default; + MoveOnlyIntComparable& operator=(MoveOnlyIntComparable&&) = default; + + friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default; +}; + +// P2404 +static_assert(check_three_way_comparable_with()); + +struct NonMovableIntComparable { + NonMovableIntComparable(int) {} + + NonMovableIntComparable(NonMovableIntComparable&&) = delete; + NonMovableIntComparable& operator=(NonMovableIntComparable&&) = delete; + + friend auto operator<=>(NonMovableIntComparable const&, NonMovableIntComparable const&) = default; +}; + +static_assert(!check_three_way_comparable_with()); + } // namespace user_defined diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp index e4058c2348f9b..15f1d30060ef1 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp @@ -41,8 +41,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++20" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++20" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++20" # endif #elif TEST_STD_VER == 23 @@ -50,8 +50,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++23" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++23" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++23" # endif #elif TEST_STD_VER > 23 @@ -59,8 +59,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++26" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++26" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++26" # endif #endif // TEST_STD_VER > 23 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index cde2f258b7732..430df6075c455 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -3329,8 +3329,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++20" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++20" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++20" # endif # ifndef __cpp_lib_constexpr_algorithms @@ -4788,8 +4788,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++23" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++23" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++23" # endif # ifndef __cpp_lib_constexpr_algorithms @@ -6475,8 +6475,8 @@ # ifndef __cpp_lib_concepts # error "__cpp_lib_concepts should be defined in c++26" # endif -# if __cpp_lib_concepts != 202002L -# error "__cpp_lib_concepts should have the value 202002L in c++26" +# if __cpp_lib_concepts != 202207L +# error "__cpp_lib_concepts should have the value 202207L in c++26" # endif # ifndef __cpp_lib_constexpr_algorithms diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp index 6d207548b2175..8b2b877092c69 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp @@ -28,9 +28,11 @@ struct NotEqualityComparable { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::equal_to::is_transparent; }); constexpr bool test() { diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp index 002ec10e07aff..0a3a1f07841b3 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp @@ -27,9 +27,11 @@ struct NotTotallyOrdered { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::greater::is_transparent; }); constexpr bool test() { diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp index ad24a98a168cf..2074599966b70 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp @@ -27,9 +27,11 @@ struct NotTotallyOrdered { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::greater_equal::is_transparent; }); constexpr bool test() { diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp index 5afb7e0ebdef4..b1a3cb8e86897 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp @@ -27,9 +27,11 @@ struct NotTotallyOrdered { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::less::is_transparent; }); constexpr bool test() { diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp index 3aa903fa6321a..739cc3b2a912e 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp @@ -27,9 +27,11 @@ struct NotTotallyOrdered { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::less_equal::is_transparent; }); constexpr bool test() { diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp index 4b46bae76ce48..5cff83143e463 100644 --- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp @@ -28,9 +28,11 @@ struct NotEqualityComparable { }; static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); +// P2404 +static_assert(std::is_invocable_v); + static_assert(requires { typename std::ranges::not_equal_to::is_transparent; }); struct PtrAndNotEqOperator { diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h index 8155f6221540c..b52e201f240ac 100644 --- a/libcxx/test/support/compare_types.h +++ b/libcxx/test/support/compare_types.h @@ -529,4 +529,30 @@ struct ForwardingTestObject { constexpr bool operator>=(const ForwardingTestObject&) const& { return false; } }; +struct move_only_equality_with_int { + move_only_equality_with_int(int); + + move_only_equality_with_int(move_only_equality_with_int&&) = default; + move_only_equality_with_int& operator=(move_only_equality_with_int&&) = default; + + move_only_equality_with_int(move_only_equality_with_int const&) = delete; + move_only_equality_with_int& operator=(move_only_equality_with_int const&) = delete; + + friend bool operator==(move_only_equality_with_int const&, move_only_equality_with_int const&) = default; + friend bool operator==(move_only_equality_with_int const&, int); +}; + +struct nonmovable_equality_with_int { + nonmovable_equality_with_int(int); + + nonmovable_equality_with_int(nonmovable_equality_with_int&&) = delete; + nonmovable_equality_with_int& operator=(nonmovable_equality_with_int&&) = delete; + + nonmovable_equality_with_int(nonmovable_equality_with_int const&) = delete; + nonmovable_equality_with_int& operator=(nonmovable_equality_with_int const&) = delete; + + friend bool operator==(nonmovable_equality_with_int const&, nonmovable_equality_with_int const&) = default; + friend bool operator==(nonmovable_equality_with_int const&, int); +}; + #endif // TEST_SUPPORT_COMPARE_TYPES_H diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index c1e579c775746..d02c8c74d3685 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -330,7 +330,7 @@ def add_version_header(tc): }, { "name": "__cpp_lib_concepts", - "values": {"c++20": 202002}, + "values": {"c++20": 202207}, "headers": ["concepts"], }, {