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 F, class... Args>
12 // concept equivalence_relation;
13 
14 #include <concepts>
15 
16 struct S1 {};
17 struct S2 {};
18 
19 struct R {
20   bool operator()(S1, S1) const;
21   bool operator()(S1, S2) const;
22   bool operator()(S2, S1) const;
23   bool operator()(S2, S2) const;
24 };
25 
26 // clang-format off
27 template<class F, class T, class U>
28 requires std::relation<F, T, U>
29 constexpr bool check_equivalence_relation_subsumes_relation() {
30   return false;
31 }
32 
33 template<class F, class T, class U>
34 requires std::equivalence_relation<F, T, U> && true
35 constexpr bool check_equivalence_relation_subsumes_relation() {
36   return true;
37 }
38 // clang-format on
39 
40 static_assert(check_equivalence_relation_subsumes_relation<int (*)(int, int),
41                                                            int, int>());
42 static_assert(check_equivalence_relation_subsumes_relation<int (*)(int, double),
43                                                            int, double>());
44 static_assert(check_equivalence_relation_subsumes_relation<R, S1, S1>());
45 static_assert(check_equivalence_relation_subsumes_relation<R, S1, S2>());
46 
47 // clang-format off
48 template<class F, class T, class U>
49 requires std::relation<F, T, U> && true
50 constexpr bool check_relation_subsumes_equivalence_relation() {
51   return true;
52 }
53 
54 template<class F, class T, class U>
55 requires std::equivalence_relation<F, T, U>
56 constexpr bool check_relation_subsumes_equivalence_relation() {
57   return false;
58 }
59 // clang-format on
60 
61 static_assert(check_relation_subsumes_equivalence_relation<int (*)(int, int),
62                                                            int, int>());
63 static_assert(check_relation_subsumes_equivalence_relation<int (*)(int, double),
64                                                            int, double>());
65 static_assert(check_relation_subsumes_equivalence_relation<R, S1, S1>());
66 static_assert(check_relation_subsumes_equivalence_relation<R, S1, S2>());
67 
68 // clang-format off
69 template<class F, class T, class U>
70 requires std::equivalence_relation<F, T, T> && std::equivalence_relation<F, U, U>
71 constexpr bool check_equivalence_relation_subsumes_itself() {
72   return false;
73 }
74 
75 template<class F, class T, class U>
76 requires std::equivalence_relation<F, T, U>
77 constexpr bool check_equivalence_relation_subsumes_itself() {
78   return true;
79 }
80 // clang-format on
81 
82 static_assert(
83     check_equivalence_relation_subsumes_itself<int (*)(int, int), int, int>());
84 static_assert(check_equivalence_relation_subsumes_itself<R, S1, S1>());
85