1 // { dg-do compile { target c++17_only } }
2 // { dg-options "-fconcepts" }
3 
4 template<typename T>
requires(T t)5 concept bool C = requires (T t) { t.mf(); };
6 
7 template<typename T>
8 concept bool CA1 = C<typename T::ca1_type>;
9 
10 template<typename T>
requires()11 concept bool CA2 = CA1<T> && requires () { typename T::ca2_type; };
12 
13 template<typename T>
requires()14 concept bool CA3 = CA2<T> && requires () { typename T::ca3_type; };
15 
16 template<typename T>
requires()17 concept bool CB1 = requires () { typename T::cb1_type; };
18 
19 template<typename T>
requires()20 concept bool CB2 = CB1<T> && requires () { typename T::cb2_type; };
21 
22 template<typename T>
requires()23 concept bool CB3 = CB2<T> && requires () { typename T::cb3_type; };
24 
25 
26 struct MC { void mf(); };
27 static_assert(C<MC>, "");
28 
29 
30 struct MA1 { using ca1_type = MC; };
31 struct MA2 : MA1 { using ca2_type = int; };
32 struct MA3 : MA2 { using ca3_type = int; };
33 static_assert(CA1<MA1>, "");
34 static_assert(CA2<MA2>, "");
35 static_assert(CA3<MA3>, "");
36 
37 struct MB1 { using cb1_type = int; };
38 struct MB2 : MB1 { using cb2_type = int; };
39 struct MB3 : MB2 { using cb3_type = int; };
40 static_assert(CB1<MB1>, "");
41 static_assert(CB2<MB2>, "");
42 static_assert(CB3<MB3>, "");
43 
44 
45 template<typename T1, typename T2>
46 struct S;
47 
48 template<CA1 T1, CB1 T2>
49 struct S<T1, T2> // Specialization #1
50 {
51   static constexpr int value = 1;
52 };
53 
54 template<CA1 T1, CB2 T2>
55   requires (!CA2<T1>)
56 struct S<T1, T2> // Specialization #2
57 {
58   static constexpr int value = 2;
59 };
60 
61 template<CA2 T1, CB3 T2>
62   requires (!CA3<T1>)
63 struct S<T1, T2> // Specialization #3
64 {
65   static constexpr int value = 3;
66 };
67 
68 static_assert(S<MA1,MB1>::value == 1, "");
69 static_assert(S<MA1,MB2>::value == 2, "");
70 static_assert(S<MA1,MB3>::value == 2, "");
71 static_assert(S<MA2,MB1>::value == 1, "");
72 static_assert(S<MA2,MB2>::value == 1, "");
73 static_assert(S<MA2,MB3>::value == 3, "");
74 static_assert(S<MA3,MB1>::value == 1, "");
75 static_assert(S<MA3,MB2>::value == 1, "");
76 static_assert(S<MA3,MB3>::value == 1, "");
77