diff --git a/stl/inc/compare b/stl/inc/compare index 64eabc340b2..76723bf8162 100644 --- a/stl/inc/compare +++ b/stl/inc/compare @@ -290,23 +290,26 @@ struct common_comparison_category { template concept _Compares_as = same_as, _Cat>; -// clang-format off _EXPORT_STD template concept three_way_comparable = _Half_equality_comparable<_Ty, _Ty> && _Half_ordered<_Ty, _Ty> - && requires(const remove_reference_t<_Ty>& __a, const remove_reference_t<_Ty>& __b) { - { __a <=> __b } -> _Compares_as<_Cat>; - }; + && requires(const remove_reference_t<_Ty>& __a, const remove_reference_t<_Ty>& __b) { + { __a <=> __b } -> _Compares_as<_Cat>; + }; _EXPORT_STD template -concept three_way_comparable_with = three_way_comparable<_Ty1, _Cat> && three_way_comparable<_Ty2, _Cat> +concept three_way_comparable_with = + three_way_comparable<_Ty1, _Cat> && three_way_comparable<_Ty2, _Cat> +#if _HAS_CXX23 + && _Comparison_common_type_with<_Ty1, _Ty2> +#else // ^^^ C++23 / C++20 vvv && common_reference_with&, const remove_reference_t<_Ty2>&> +#endif // C++20 && three_way_comparable&, const remove_reference_t<_Ty2>&>, _Cat> && _Weakly_equality_comparable_with<_Ty1, _Ty2> && _Partially_ordered_with<_Ty1, _Ty2> && requires(const remove_reference_t<_Ty1>& __t, const remove_reference_t<_Ty2>& __u) { - { __t <=> __u } -> _Compares_as<_Cat>; - { __u <=> __t } -> _Compares_as<_Cat>; - }; -// clang-format on + { __t <=> __u } -> _Compares_as<_Cat>; + { __u <=> __t } -> _Compares_as<_Cat>; + }; _EXPORT_STD template using compare_three_way_result_t = diff --git a/stl/inc/concepts b/stl/inc/concepts index c00665e58a2..35845c6c674 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -206,9 +206,26 @@ concept _Weakly_equality_comparable_with = _EXPORT_STD template concept equality_comparable = _Half_equality_comparable<_Ty, _Ty>; +#if _HAS_CXX23 +template > +concept _Comparison_common_type_with_impl = + same_as<_Ref, common_reference_t> + && requires { + requires convertible_to || convertible_to<_Ty1, const _Ref&>; + requires convertible_to || convertible_to<_Ty2, const _Ref&>; + }; + +template +concept _Comparison_common_type_with = _Comparison_common_type_with_impl, remove_cvref_t<_Ty2>>; +#endif // _HAS_CXX23 + _EXPORT_STD template concept equality_comparable_with = equality_comparable<_Ty1> && equality_comparable<_Ty2> +#if _HAS_CXX23 + && _Comparison_common_type_with<_Ty1, _Ty2> +#else // ^^^ C++23 / C++20 vvv && common_reference_with&, const remove_reference_t<_Ty2>&> +#endif // C++20 && equality_comparable&, const remove_reference_t<_Ty2>&>> && _Weakly_equality_comparable_with<_Ty1, _Ty2>; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 88cf2c26aeb..c3f4caef87f 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -333,6 +333,7 @@ // (missing views::zip_transform, views::adjacent, and views::adjacent_transform) // P2322R6 ranges::fold_left, ranges::fold_right, Etc. // P2387R3 Pipe Support For User-Defined Range Adaptors +// P2404R3 Move-Only Types For Comparison Concepts // P2417R2 More constexpr bitset // P2438R2 string::substr() && // P2440R1 ranges::iota, ranges::shift_left, ranges::shift_right @@ -1565,7 +1566,11 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #if _HAS_CXX20 #if !defined(__EDG__) || defined(__INTELLISENSE__) // TRANSITION, GH-395 -#define __cpp_lib_concepts 202002L +#if _HAS_CXX23 // TRANSITION, GH-395 - move down to "macros with language mode sensitivity" section +#define __cpp_lib_concepts 202207L // P2404R3 Move-Only Types For Comparison Concepts +#else // ^^^ C++23 / C++20 vvv +#define __cpp_lib_concepts 202002L // P1964R2 Replacing boolean With boolean-testable +#endif // C++20 #endif // !defined(__EDG__) || defined(__INTELLISENSE__) #ifdef __cpp_lib_concepts diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 764505bbc2c..81b556d987b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -54,6 +54,16 @@ std/ranges/range.access/end.pass.cpp FAIL std/ranges/range.access/rbegin.pass.cpp FAIL std/ranges/range.access/rend.pass.cpp FAIL +# libc++ has not implemented P2404R3: "Move-Only Types For Comparison Concepts" +std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp FAIL +std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp FAIL +std/utilities/function.objects/range.cmp/equal_to.pass.cpp FAIL +std/utilities/function.objects/range.cmp/greater.pass.cpp FAIL +std/utilities/function.objects/range.cmp/greater_equal.pass.cpp FAIL +std/utilities/function.objects/range.cmp/less.pass.cpp FAIL +std/utilities/function.objects/range.cmp/less_equal.pass.cpp FAIL +std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp FAIL + # Various bogosity (LLVM-D141004) std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp:0 FAIL std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp:0 FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 428e61c57c8..38d1cb6bebc 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -54,6 +54,16 @@ ranges\range.access\end.pass.cpp ranges\range.access\rbegin.pass.cpp ranges\range.access\rend.pass.cpp +# libc++ has not implemented P2404R3: "Move-Only Types For Comparison Concepts" +algorithms\alg.sorting\alg.sort\partial.sort.copy\ranges_partial_sort_copy.pass.cpp +language.support\support.limits\support.limits.general\concepts.version.compile.pass.cpp +utilities\function.objects\range.cmp\equal_to.pass.cpp +utilities\function.objects\range.cmp\greater.pass.cpp +utilities\function.objects\range.cmp\greater_equal.pass.cpp +utilities\function.objects\range.cmp\less.pass.cpp +utilities\function.objects\range.cmp\less_equal.pass.cpp +utilities\function.objects\range.cmp\not_equal_to.pass.cpp + # Various bogosity (LLVM-D141004) utilities\utility\mem.res\mem.poly.allocator.class\mem.poly.allocator.mem\construct_pair_const_lvalue_pair.pass.cpp utilities\utility\mem.res\mem.poly.allocator.class\mem.poly.allocator.mem\construct_pair_values.pass.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 9652c56a554..81c12978219 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -567,6 +567,7 @@ tests\P2322R6_ranges_alg_fold tests\P2387R3_bind_back tests\P2387R3_pipe_support_for_user_defined_range_adaptors tests\P2401R0_conditional_noexcept_for_exchange +tests\P2404R3_move_only_types_for_comparison_concepts tests\P2408R5_ranges_iterators_to_classic_algorithms tests\P2415R2_owning_view tests\P2417R2_constexpr_bitset diff --git a/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/env.lst b/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/env.lst new file mode 100644 index 00000000000..18e2d7c71ec --- /dev/null +++ b/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/test.compile.pass.cpp b/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/test.compile.pass.cpp new file mode 100644 index 00000000000..6d266d217f7 --- /dev/null +++ b/tests/std/tests/P2404R3_move_only_types_for_comparison_concepts/test.compile.pass.cpp @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +struct MoveOnly { + MoveOnly(int); // not defined + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) = default; + MoveOnly& operator=(MoveOnly&&) = default; + + strong_ordering operator<=>(const MoveOnly&) const = default; + strong_ordering operator<=>(int) const; // not defined +}; + +// Check three_way_comparable_with +static_assert(three_way_comparable_with); +static_assert(three_way_comparable_with); +static_assert(three_way_comparable_with); +static_assert(three_way_comparable_with); + +// Check equality_comparable_with +static_assert(equality_comparable_with); +static_assert(equality_comparable_with); +static_assert(equality_comparable_with, nullptr_t>); +static_assert(equality_comparable_with>); + +// Check totally_ordered_with +static_assert(totally_ordered_with); +static_assert(totally_ordered_with); + +// Check [diff.cpp20.concepts] +// clang-format off +template + requires equality_comparable_with +bool attempted_equals(const T&, const U&); // not defined + +template + requires common_reference_with&, const remove_reference_t&> +bool attempted_equals(const T&, const U&); // not defined +// clang-format on + +template +constexpr bool check_diff_cpp20_concepts = !requires(T p) { attempted_equals(p, nullptr); }; + +static_assert(check_diff_cpp20_concepts>); + +int main() {} // COMPILE-ONLY diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index d2c679c1dc9..4e15042f407 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -458,7 +458,15 @@ STATIC_ASSERT(__cpp_lib_clamp == 201603L); STATIC_ASSERT(__cpp_lib_complex_udls == 201309L); #endif -#if _HAS_CXX20 && !defined(__EDG__) // TRANSITION, GH-395 +#if _HAS_CXX23 && !defined(__EDG__) // TRANSITION, GH-395 +#ifndef __cpp_lib_concepts +#error __cpp_lib_concepts is not defined +#elif __cpp_lib_concepts != 202207L +#error __cpp_lib_concepts is not 202207L +#else +STATIC_ASSERT(__cpp_lib_concepts == 202207L); +#endif +#elif _HAS_CXX20 && !defined(__EDG__) // TRANSITION, GH-395 #ifndef __cpp_lib_concepts #error __cpp_lib_concepts is not defined #elif __cpp_lib_concepts != 202002L