diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -76,7 +76,7 @@ "`P1209R0 `__","LWG","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","San Diego","|Complete|","8.0" "`P1210R0 `__","LWG","Completing the Rebase of Library Fundamentals, Version 3, Working Draft","San Diego","* *","" "`P1236R1 `__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *","" -"`P1248R1 `__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","* *","" +"`P1248R1 `__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","|Complete|","13.0" "`P1285R0 `__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *","" "`P1353R0 `__","CWG","Missing feature test macros","San Diego","* *","" "","","","","","" diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -426,7 +426,25 @@ template concept regular_invocable = invocable<_Fn, _Args...>; -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) +// [concept.predicate] +template +concept predicate = + regular_invocable<_Fn, _Args...> && __boolean_testable>; + +// [concept.relation] +template +concept relation = + predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && + predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; + +// [concept.equiv] +template +concept equivalence_relation = relation<_Rp, _Tp, _Up>; + +// [concept.strictweakorder] +template +concept strict_weak_order = relation<_Rp, _Tp, _Up>; +#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept equivalence_relation; + +#include + +static_assert(std::equivalence_relation); +static_assert(std::equivalence_relation); +static_assert(std::equivalence_relation); + +static_assert(!std::equivalence_relation); +static_assert(!std::equivalence_relation); +static_assert(!std::equivalence_relation); + +static_assert( + !std::equivalence_relation); +static_assert(!std::equivalence_relation); + +struct S1 {}; +static_assert(std::relation); +static_assert(std::relation); + +struct S2 {}; + +struct P1 { + bool operator()(S1, S1) const; +}; +static_assert(std::equivalence_relation); + +struct P2 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; +}; +static_assert(!std::equivalence_relation); + +struct P3 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; +}; +static_assert(!std::equivalence_relation); + +struct P4 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; +static_assert(std::equivalence_relation); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept equivalence_relation; + +#include + +struct S1 {}; +struct S2 {}; + +struct R { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; + +// clang-format off +template +requires std::relation +[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() { + return false; +} + +template +requires std::equivalence_relation && true +[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() { + return true; +} +// clang-format on + +static_assert(check_equivalence_relation_subsumes_relation()); +static_assert(check_equivalence_relation_subsumes_relation()); +static_assert(check_equivalence_relation_subsumes_relation()); +static_assert(check_equivalence_relation_subsumes_relation()); + +// clang-format off +template +requires std::relation && true +[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() { + return true; +} + +template +requires std::equivalence_relation +[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() { + return false; +} +// clang-format on + +static_assert(check_relation_subsumes_equivalence_relation()); +static_assert(check_relation_subsumes_equivalence_relation()); +static_assert(check_relation_subsumes_equivalence_relation()); +static_assert(check_relation_subsumes_equivalence_relation()); + +// clang-format off +template +requires std::equivalence_relation && std::equivalence_relation +[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() { + return false; +} + +template +requires std::equivalence_relation +[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() { + return true; +} +// clang-format on + +static_assert( + check_equivalence_relation_subsumes_itself()); +static_assert(check_equivalence_relation_subsumes_itself()); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept predicate; + +#include + +static_assert(std::predicate); +static_assert(std::predicate); +static_assert(std::predicate); + +static_assert(!std::predicate); +static_assert(!std::predicate); +static_assert(!std::predicate); + +struct S {}; + +static_assert(!std::predicate); +static_assert(!std::predicate); +static_assert(std::predicate); +static_assert(std::predicate); +static_assert(std::predicate); +static_assert(!std::predicate); +static_assert(!std::predicate); + +static_assert(!std::predicate); +static_assert(!std::predicate); +static_assert(!std::predicate); +static_assert(std::predicate); + +struct Predicate { + bool operator()(int, double, char); +}; +static_assert(std::predicate); +static_assert(std::predicate); +static_assert(!std::predicate); +static_assert(!std::predicate); + +[[nodiscard]] constexpr bool check_lambda(auto) { return false; } + +[[nodiscard]] constexpr bool check_lambda(std::predicate auto) { return true; } + +static_assert(check_lambda([] { return std::true_type(); })); +static_assert(check_lambda([]() -> int* { return nullptr; })); + +struct boolean { + operator bool() const noexcept; +}; +static_assert(check_lambda([] { return boolean(); })); + +struct explicit_bool { + explicit operator bool() const noexcept; +}; +static_assert(!check_lambda([] { return explicit_bool(); })); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept predicate; + +#include + +[[nodiscard]] constexpr bool check_subsumption(std::regular_invocable auto) { + return false; +} + +// clang-format off +template +requires std::predicate && true +[[nodiscard]] constexpr bool check_subsumption(F) +{ + return true; +} +// clang-format on + +static_assert(!check_subsumption([] {})); +static_assert(check_subsumption([] { return true; })); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept relation; + +#include + +static_assert(std::relation); +static_assert(std::relation); +static_assert(std::relation); + +static_assert(!std::relation); +static_assert(!std::relation); +static_assert(!std::relation); +static_assert(!std::relation); +static_assert(!std::relation); + +struct S1 {}; +static_assert(std::relation); +static_assert(std::relation); + +struct S2 {}; + +struct P1 { + bool operator()(S1, S1) const; +}; +static_assert(std::relation); + +struct P2 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; +}; +static_assert(!std::relation); + +struct P3 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; +}; +static_assert(!std::relation); + +struct P4 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; +static_assert(std::relation); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept relation; + +#include + +struct S1 {}; +struct S2 {}; + +struct R { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; + +// clang-format off +template +requires std::predicate && std::predicate && + std::predicate && std::predicate +[[nodiscard]] constexpr bool check_relation_subsumes_predicate() { + return false; +} + +template +requires std::relation && true +[[nodiscard]] constexpr bool check_relation_subsumes_predicate() { + return true; +} +// clang-format on + +static_assert( + check_relation_subsumes_predicate()); +static_assert( + check_relation_subsumes_predicate()); +static_assert(check_relation_subsumes_predicate()); +static_assert(check_relation_subsumes_predicate()); + +// clang-format off +template +requires std::relation && std::relation +[[nodiscard]] constexpr bool check_relation_subsumes_itself() { + return false; +} + +template +requires std::relation +[[nodiscard]] constexpr bool check_relation_subsumes_itself() { + return true; +} +// clang-format on + +static_assert(check_relation_subsumes_itself()); +static_assert(check_relation_subsumes_itself()); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept strict_weak_order; + +#include + +static_assert(std::strict_weak_order); +static_assert(std::strict_weak_order); +static_assert(std::strict_weak_order); + +static_assert(!std::strict_weak_order); +static_assert(!std::strict_weak_order); +static_assert(!std::strict_weak_order); + +static_assert(!std::strict_weak_order); +static_assert(!std::strict_weak_order); + +struct S1 {}; +static_assert(std::strict_weak_order); +static_assert(std::strict_weak_order); + +struct S2 {}; + +struct P1 { + bool operator()(S1, S1) const; +}; +static_assert(std::strict_weak_order); + +struct P2 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; +}; +static_assert(!std::strict_weak_order); + +struct P3 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; +}; +static_assert(!std::strict_weak_order); + +struct P4 { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; +static_assert(std::strict_weak_order); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept strict_weak_order; + +#include + +struct S1 {}; +struct S2 {}; + +struct R { + bool operator()(S1, S1) const; + bool operator()(S1, S2) const; + bool operator()(S2, S1) const; + bool operator()(S2, S2) const; +}; + +// clang-format off +template +requires std::relation +[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() { + return false; +} + +template +requires std::strict_weak_order && true +[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() { + return true; +} +// clang-format on + +static_assert( + check_strict_weak_order_subsumes_relation()); +static_assert(check_strict_weak_order_subsumes_relation()); +static_assert(check_strict_weak_order_subsumes_relation()); +static_assert(check_strict_weak_order_subsumes_relation()); + +// clang-format off +template +requires std::relation && true +[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() { + return true; +} + +template +requires std::strict_weak_order +[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() { + return false; +} +// clang-format on + +static_assert( + check_relation_subsumes_strict_weak_order()); +static_assert(check_relation_subsumes_strict_weak_order()); +static_assert(check_relation_subsumes_strict_weak_order()); +static_assert(check_relation_subsumes_strict_weak_order()); + +// clang-format off +template +requires std::strict_weak_order && std::strict_weak_order +[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() { + return false; +} + +template +requires std::strict_weak_order +[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() { + return true; +} +// clang-format on + +static_assert( + check_strict_weak_order_subsumes_itself()); +static_assert(check_strict_weak_order_subsumes_itself());