// { dg-do compile { target c++17 } } // { dg-options "-fconcepts" } template concept C = requires (T t) { t.mf(); }; template concept CA1 = C; template concept CA2 = CA1 && requires () { typename T::ca2_type; }; template concept CA3 = CA2 && requires () { typename T::ca3_type; }; template concept CB1 = requires () { typename T::cb1_type; }; template concept CB2 = CB1 && requires () { typename T::cb2_type; }; template concept CB3 = CB2 && requires () { typename T::cb3_type; }; struct MC { void mf(); }; static_assert(C, ""); struct MA1 { using ca1_type = MC; }; struct MA2 : MA1 { using ca2_type = int; }; struct MA3 : MA2 { using ca3_type = int; }; static_assert(CA1, ""); static_assert(CA2, ""); static_assert(CA3, ""); struct MB1 { using cb1_type = int; }; struct MB2 : MB1 { using cb2_type = int; }; struct MB3 : MB2 { using cb3_type = int; }; static_assert(CB1, ""); static_assert(CB2, ""); static_assert(CB3, ""); template struct S; template struct S // Specialization #1 { static constexpr int value = 1; }; template requires (!CA2) struct S // Specialization #2 { static constexpr int value = 2; }; template requires (!CA3) struct S // Specialization #3 { static constexpr int value = 3; }; static_assert(S::value == 1, ""); static_assert(S::value == 2, ""); static_assert(S::value == 2, ""); static_assert(S::value == 1, ""); static_assert(S::value == 1, ""); static_assert(S::value == 3, ""); static_assert(S::value == 1, ""); static_assert(S::value == 1, ""); static_assert(S::value == 1, "");