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