diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index a89d4038785cd..f9304a997ccbc 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -198,7 +198,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_char8_t`` ``201907L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_concepts`` ``202002L`` + ``__cpp_lib_concepts`` ``202207L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index 6cbc0baf29487..7bc431fed4e14 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -47,6 +47,7 @@ Implemented Papers - P1222R4: A Standard ``flat_set`` (`Github `__) - P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github `__) - P3247R2: Deprecate the notion of trivial types (`Github `__) +- P2404R3 - Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with`` (`Github `__) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index c26363bcda796..09dba5410fc32 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -67,7 +67,7 @@ "`P2302R4 `__","``std::ranges::contains``","2022-07 (Virtual)","|Complete|","19","" "`P2322R6 `__","``ranges::fold``","2022-07 (Virtual)","","","" "`P2374R4 `__","``views::cartesian_product``","2022-07 (Virtual)","","","" -"`P2404R3 `__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","","","" +"`P2404R3 `__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","|Complete|","21","" "`P2408R5 `__","Ranges iterators as inputs to non-Ranges algorithms","2022-07 (Virtual)","","","" "`P2417R2 `__","A more ``constexpr`` ``bitset``","2022-07 (Virtual)","|Complete|","16","" "`P2419R2 `__","Clarify handling of encodings in localized formatting of chrono types","2022-07 (Virtual)","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 43cefd5600646..0a2f32361a86b 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 7f625cefed1c2..1021daabc7c3c 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1073,6 +1073,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 65fae111dc8ed..0bfdcc8b0c53f 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -60,7 +60,7 @@ __cpp_lib_chrono 201611L __cpp_lib_chrono_udls 201304L __cpp_lib_clamp 201603L __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 @@ -400,7 +400,7 @@ __cpp_lib_void_t 201411L # if _LIBCPP_HAS_CHAR8_T # define __cpp_lib_char8_t 201907L # endif -# 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 0afbe582ba896..1fe890281c684 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 @@ -1116,4 +1116,12 @@ 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()); + +// For testing +static_assert(!std::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..35fb2d6dc84b2 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,31 @@ 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()); + +// For testing +static_assert(!std::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 d9b2c43ecbd12..403c69dd96d0e 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 b1cc4afd30696..93017df9b8c64 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 @@ -3267,8 +3267,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 @@ -4704,8 +4704,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 @@ -6375,8 +6375,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 82f0d09db5c36..860f9b1b1eabf 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -320,7 +320,7 @@ def add_version_header(tc): }, { "name": "__cpp_lib_concepts", - "values": {"c++20": 202002}, + "values": {"c++20": 202207}, "headers": ["concepts"], }, { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy