1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | |
11 | // template<class I1, class I2, class R, class P1, class P2> |
12 | // concept indirectly_comparable; |
13 | |
14 | #include <functional> |
15 | #include <iterator> |
16 | #include <type_traits> |
17 | |
18 | #include "test_macros.h" |
19 | |
20 | struct Deref { |
21 | int operator()(int*) const; |
22 | }; |
23 | |
24 | static_assert(!std::indirectly_comparable<int, int, std::less<int>>); // not dereferenceable |
25 | static_assert(!std::indirectly_comparable<int*, int*, int>); // not a predicate |
26 | static_assert( std::indirectly_comparable<int*, int*, std::less<int>>); |
27 | static_assert(!std::indirectly_comparable<int**, int*, std::less<int>>); |
28 | static_assert( std::indirectly_comparable<int**, int*, std::less<int>, Deref>); |
29 | static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, Deref, Deref>); |
30 | static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, std::identity, Deref>); |
31 | static_assert( std::indirectly_comparable<int*, int**, std::less<int>, std::identity, Deref>); |
32 | |
33 | template<class F> |
34 | requires std::indirectly_comparable<int*, char*, F> |
35 | && true // This true is an additional atomic constraint as a tie breaker |
36 | constexpr bool subsumes(F) { return true; } |
37 | |
38 | template<class F> |
39 | requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>> |
40 | void subsumes(F); |
41 | |
42 | template<class F> |
43 | requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>> |
44 | && true // This true is an additional atomic constraint as a tie breaker |
45 | constexpr bool is_subsumed(F) { return true; } |
46 | |
47 | template<class F> |
48 | requires std::indirectly_comparable<int*, char*, F> |
49 | void is_subsumed(F); |
50 | |
51 | static_assert(subsumes(std::less<int>())); |
52 | static_assert(is_subsumed(std::less<int>())); |
53 | |
54 | // Test ADL-proofing (P2538R1) |
55 | #if TEST_STD_VER >= 26 || defined(_LIBCPP_VERSION) |
56 | struct Incomplete; |
57 | template<class T> struct Holder { T t; }; |
58 | static_assert(std::indirectly_comparable<Holder<Incomplete>**, Holder<Incomplete>**, std::less<Holder<Incomplete>*>>); |
59 | static_assert(!std::indirectly_comparable<Holder<Incomplete>**, Holder<Incomplete>**, Holder<Incomplete>*>); |
60 | #endif |
61 | |