1 // { dg-do compile { target c++2a } }
2 // { dg-additional-options "-fconcepts-ts" }
3 
4 typedef int size_t;
5 template <typename _Tp> struct A { static constexpr _Tp value = 1; };
6 template <typename _Tp> _Tp declval();
7 template <typename _From, typename _To> struct __is_convertible_helper {
8   template <typename, typename> static A<bool> __test(int);
9   typedef decltype(__test<_From, _To>(0)) type;
10 };
11 template <typename, typename>
12 struct is_convertible : __is_convertible_helper<int, int>::type {};
13 template <typename> struct remove_reference;
14 template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
15 struct base;
16 struct general;
17 template <typename _Tp, _Tp...> struct B;
18 template <typename _Tp, _Tp> using make_integer_sequence = B<int>;
19 template <size_t... _Idx> using index_sequence = B<size_t, _Idx...>;
20 template <size_t _Num>
21 using make_index_sequence = make_integer_sequence<size_t, _Num>;
22 template <bool...> struct and_c_impl { static constexpr bool value = true; };
23 template <bool...> constexpr bool and_c() { return and_c_impl<>::value; }
24 
25 template <class X, class Y> concept bool cpt_Convertible() {
26   return is_convertible<X, Y>::value;
27 }
28 
29 template <class T> using uncvref_t = typename remove_reference<T>::type;
30 struct Plus;
31 using index_t = int;
32 template <class> bool cpt_Index;
33 template <class... Extents>
34 requires and_c<cpt_Index<Extents>()...>() class Dimensionality;
35 namespace detail_concept {
36 template <class> bool match_dimensionality;
37 template <class... Extents>
38 constexpr bool match_dimensionality<Dimensionality<Extents...>> = true;
39 }
40 template <class X> concept bool cpt_Dimensionality() {
41   return detail_concept::match_dimensionality<X>;
42 }
43 
44 template <class X> concept bool cpt_Shaped() { return requires(X x){{x};}; }
45 
46 template <class X> concept bool cpt_Dimensioned() { return cpt_Shaped<X>(); }
47 
48 template <class... Extents>
49 requires and_c<cpt_Index<Extents>()...>() class Dimensionality {
50 public:
51   static constexpr size_t num_dimensions = sizeof...(Extents);
52 };
53 template <index_t...> using DimensionalityC = Dimensionality<>;
54 template <class> struct dimensionality_type_impl;
55 template <cpt_Dimensioned X> struct dimensionality_type_impl<X> {
56   using type = uncvref_t<decltype(declval<X>().dimensionality())>;
57 };
58 template <cpt_Dimensioned X>
59 using dimensionality_type = typename dimensionality_type_impl<X>::type;
60 template <class Functor, class... Expressibles>
61 requires requires(Functor functor, Expressibles... expressibles) {
62   map_expressions_impl(functor, expressibles...);
63 }
64 
65 decltype(auto) map_impl(Functor, Expressibles...);
66 void cpt_ContinualScalar();
67 template <class> concept bool cpt_Scalar() { return cpt_ContinualScalar; }
68 
69 template <class X> concept bool cpt_FlatEvaluator() {
70   return requires(X x){{x}->cpt_Scalar;};
71 }
72 
73 template <class, class> bool k_evaluator_impl;
74 template <size_t... Indexes, class Evaluator>
75 constexpr bool k_evaluator_impl<index_sequence<Indexes...>, Evaluator> = true;
76 template <class X, size_t K> concept bool cpt_KEvaluator() {
77   return k_evaluator_impl<make_index_sequence<K>, X>;
78 }
79 
80 template <class X, size_t K> concept bool cpt_KCompatibleEvaluator() {
81   return cpt_KEvaluator<X, K>();
82 }
83 
84 template <class X> concept bool cpt_Structure() {
85   return cpt_Convertible<X, base>();
86 }
87 
88 template <cpt_Dimensionality Dimensionality, cpt_Structure,
89           cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
90 class NumericArrayExpression;
91 namespace detail_concept {
92 
93 template <class> bool match_numeric_array_expression;
94 
95 template <cpt_Dimensionality Dimensionality,
96           cpt_Structure Structure,
97           cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
98 constexpr bool match_numeric_array_expression<
99     NumericArrayExpression<Dimensionality, Structure, Evaluator>> = true;
100 
101 }
102 template <class X> concept bool cpt_NumericArrayExpression() {
103   return detail_concept::match_numeric_array_expression<X>;
104 }
105 
106 namespace expression_traits {
107 namespace detail_expression_traits {
108 template <class...> struct first_numeric_array_expression_impl;
109 template <cpt_NumericArrayExpression ExpressionFirst, class... ExpressionsRest>
110 struct first_numeric_array_expression_impl<ExpressionFirst,
111                                            ExpressionsRest...> {
112   using type = ExpressionFirst;
113 };
114 }
115 template <class... Expressions>
116 using first_numeric_array_expression =
117     typename detail_expression_traits::first_numeric_array_expression_impl<
118         Expressions...>::type;
119 template <class... Expressions>
120 using first_expression_dimensionality =
121     dimensionality_type<first_numeric_array_expression<Expressions...>>;
122 }
123 template <cpt_Dimensionality Dimensionality, cpt_Structure,
124           cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
125 class NumericArrayExpression {
126 public:
127   NumericArrayExpression(Dimensionality, Evaluator) {}
128   Dimensionality &dimensionality();
129 };
130 
131 template <cpt_Structure Structure, cpt_Dimensionality Dimensionality,
132           cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
133 auto make_numeric_array_expression(Dimensionality dimensionality,
134                                    Evaluator evaluator) {
135   return NumericArrayExpression<Dimensionality, Structure, Evaluator>(
136       dimensionality, evaluator);
137 }
138 
139 template <size_t, class Functor, class... Evaluators>
140 auto make_map_evaluator_impl(Functor) requires
141     and_(cpt_FlatEvaluator<Evaluators>()...);
142 template <class Functor, class... Expressions>
143 requires
144 requires(Expressions... expressions,
145          expression_traits::first_expression_dimensionality<Expressions...>
146              dimensionality) {
147   make_map_evaluator_impl<decltype(dimensionality)::num_dimensions>(
148       expressions...);
149 }
150 
151 decltype(auto) map_expressions_impl(Functor, Expressions...);
152 template <class Functor, class... Expressibles> concept bool cpt_Mappable() {
153   return requires(Functor functor, Expressibles... expressibles) {
154     map_impl(functor, expressibles...);
155   };
156 }
157 
158 void ____C_A_T_C_H____T_E_S_T____8() {
159   auto e1 = make_numeric_array_expression<general>(DimensionalityC<>(), [] {});
160   using E1 = decltype(e1);
161   cpt_Mappable<Plus, E1>();
162 }
163