summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp2a/concepts-pr67862.C
blob: 222e528091318d4aea9400576ba0138fb35aed95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// { dg-do compile { target c++2a } }
// { dg-additional-options "-fconcepts-ts" }

typedef int size_t;
template <typename _Tp> struct A { static constexpr _Tp value = 1; };
template <typename _Tp> _Tp declval();
template <typename _From, typename _To> struct __is_convertible_helper {
  template <typename, typename> static A<bool> __test(int);
  typedef decltype(__test<_From, _To>(0)) type;
};
template <typename, typename>
struct is_convertible : __is_convertible_helper<int, int>::type {};
template <typename> struct remove_reference;
template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; };
struct base;
struct general;
template <typename _Tp, _Tp...> struct B;
template <typename _Tp, _Tp> using make_integer_sequence = B<int>;
template <size_t... _Idx> using index_sequence = B<size_t, _Idx...>;
template <size_t _Num>
using make_index_sequence = make_integer_sequence<size_t, _Num>;
template <bool...> struct and_c_impl { static constexpr bool value = true; };
template <bool...> constexpr bool and_c() { return and_c_impl<>::value; }

template <class X, class Y> concept bool cpt_Convertible() {
  return is_convertible<X, Y>::value;
}

template <class T> using uncvref_t = typename remove_reference<T>::type;
struct Plus;
using index_t = int;
template <class> bool cpt_Index;
template <class... Extents>
requires and_c<cpt_Index<Extents>()...>() class Dimensionality;
namespace detail_concept {
template <class> bool match_dimensionality;
template <class... Extents>
constexpr bool match_dimensionality<Dimensionality<Extents...>> = true;
}
template <class X> concept bool cpt_Dimensionality() {
  return detail_concept::match_dimensionality<X>;
}

template <class X> concept bool cpt_Shaped() { return requires(X x){{x};}; }

template <class X> concept bool cpt_Dimensioned() { return cpt_Shaped<X>(); }

template <class... Extents>
requires and_c<cpt_Index<Extents>()...>() class Dimensionality {
public:
  static constexpr size_t num_dimensions = sizeof...(Extents);
};
template <index_t...> using DimensionalityC = Dimensionality<>;
template <class> struct dimensionality_type_impl;
template <cpt_Dimensioned X> struct dimensionality_type_impl<X> {
  using type = uncvref_t<decltype(declval<X>().dimensionality())>;
};
template <cpt_Dimensioned X>
using dimensionality_type = typename dimensionality_type_impl<X>::type;
template <class Functor, class... Expressibles>
requires requires(Functor functor, Expressibles... expressibles) {
  map_expressions_impl(functor, expressibles...);
}

decltype(auto) map_impl(Functor, Expressibles...);
void cpt_ContinualScalar();
template <class> concept bool cpt_Scalar() { return cpt_ContinualScalar; }

template <class X> concept bool cpt_FlatEvaluator() {
  return requires(X x){{x}->cpt_Scalar;};
}

template <class, class> bool k_evaluator_impl;
template <size_t... Indexes, class Evaluator>
constexpr bool k_evaluator_impl<index_sequence<Indexes...>, Evaluator> = true;
template <class X, size_t K> concept bool cpt_KEvaluator() {
  return k_evaluator_impl<make_index_sequence<K>, X>;
}

template <class X, size_t K> concept bool cpt_KCompatibleEvaluator() {
  return cpt_KEvaluator<X, K>();
}

template <class X> concept bool cpt_Structure() {
  return cpt_Convertible<X, base>();
}

template <cpt_Dimensionality Dimensionality, cpt_Structure,
          cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
class NumericArrayExpression;
namespace detail_concept {

template <class> bool match_numeric_array_expression;

template <cpt_Dimensionality Dimensionality,
          cpt_Structure Structure,
          cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
constexpr bool match_numeric_array_expression<
    NumericArrayExpression<Dimensionality, Structure, Evaluator>> = true;

}
template <class X> concept bool cpt_NumericArrayExpression() {
  return detail_concept::match_numeric_array_expression<X>;
}

namespace expression_traits {
namespace detail_expression_traits {
template <class...> struct first_numeric_array_expression_impl;
template <cpt_NumericArrayExpression ExpressionFirst, class... ExpressionsRest>
struct first_numeric_array_expression_impl<ExpressionFirst,
                                           ExpressionsRest...> {
  using type = ExpressionFirst;
};
}
template <class... Expressions>
using first_numeric_array_expression =
    typename detail_expression_traits::first_numeric_array_expression_impl<
        Expressions...>::type;
template <class... Expressions>
using first_expression_dimensionality =
    dimensionality_type<first_numeric_array_expression<Expressions...>>;
}
template <cpt_Dimensionality Dimensionality, cpt_Structure,
          cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
class NumericArrayExpression {
public:
  NumericArrayExpression(Dimensionality, Evaluator) {}
  Dimensionality &dimensionality();
};

template <cpt_Structure Structure, cpt_Dimensionality Dimensionality,
          cpt_KCompatibleEvaluator<Dimensionality::num_dimensions> Evaluator>
auto make_numeric_array_expression(Dimensionality dimensionality,
                                   Evaluator evaluator) {
  return NumericArrayExpression<Dimensionality, Structure, Evaluator>(
      dimensionality, evaluator);
}

template <size_t, class Functor, class... Evaluators>
auto make_map_evaluator_impl(Functor) requires
    and_(cpt_FlatEvaluator<Evaluators>()...);
template <class Functor, class... Expressions>
requires
requires(Expressions... expressions,
         expression_traits::first_expression_dimensionality<Expressions...>
             dimensionality) {
  make_map_evaluator_impl<decltype(dimensionality)::num_dimensions>(
      expressions...);
}

decltype(auto) map_expressions_impl(Functor, Expressions...);
template <class Functor, class... Expressibles> concept bool cpt_Mappable() {
  return requires(Functor functor, Expressibles... expressibles) {
    map_impl(functor, expressibles...);
  };
}

void ____C_A_T_C_H____T_E_S_T____8() {
  auto e1 = make_numeric_array_expression<general>(DimensionalityC<>(), [] {});
  using E1 = decltype(e1);
  cpt_Mappable<Plus, E1>();
}