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
subsumes(F)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
is_subsumed(F)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