File: simple-requirement.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (241 lines) | stat: -rw-r--r-- 7,916 bytes parent folder | download | duplicates (10)
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// RUN: %clang_cc1 %s -I%S -std=c++2a -verify

namespace std { struct type_info; }

static_assert(requires { 0; });
static_assert(requires { "aaaa"; });
static_assert(requires { (0).da; }); // expected-error{{member reference base type 'int' is not a structure or union}}

struct A {};
struct B {
    B operator+(const B &other) const { return other; }
};
struct C {
    C operator+(C &other) const { return other; }
};

template<typename T> requires requires (T a, const T& b) { a + b; }
// expected-note@-1{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}}
// expected-note@-2{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}}
struct r1 {};

using r1i1 = r1<int>;
using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}}
using r1i3 = r1<B>;
using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}}

struct D { void foo() {} };

template<typename T> requires requires (T a) { a.foo(); }
// expected-note@-1{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}}
// expected-note@-2{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}}
// expected-note@-3{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}}
struct r2 {};

using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}}
using r2i3 = r2<D>;
using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}}

template<typename T> requires requires { sizeof(T); }
// expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}}
// expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}}
struct r3 {};

using r3i1 = r3<int>;
using r3i2 = r3<A>;
using r3i3 = r3<A &>;
using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}}
using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}}

template<typename T> requires requires (T t) { 0; "a"; (void)'a'; }
struct r4 {};

using r4i1 = r4<int>;
using r4i2 = r4<int[10]>;
using r4i3 = r4<int(int)>;

template<class T> void f(T) = delete;
template<class T> requires (sizeof(T) == 1) void f(T) { }

template<typename T> requires requires(T t) { f(t); }
// expected-note@-1{{because 'f(t)' would be invalid: call to deleted function 'f'}}
struct r5 {};

using r5i1 = r5<int>;
// expected-error@-1 {{constraints not satisfied for class template 'r5' [with T = int]}}
using r5i2 = r5<char>;

template<typename T>
struct E {
  struct non_default_constructible { non_default_constructible(T t) { } };
};

template<typename T> requires requires(T t) { typename E<T>::non_default_constructible{}; }
// expected-note@-1 {{because 'typename E<T>::non_default_constructible{}' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}}
struct r6 {};

using r6i1 = r6<int>;
// expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}

template<typename T> requires requires(T t) { typename E<T>::non_default_constructible(); }
// expected-note@-1 {{because 'typename E<T>::non_default_constructible()' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}}
struct r7 {};

using r7i1 = r7<int>;
// expected-error@-1 {{constraints not satisfied for class template 'r7' [with T = int]}}

// C++ [expr.prim.req.simple] Example
namespace std_example {
  template<typename T> concept C =
    requires (T a, T b) { // expected-note{{because 'a' would be invalid: argument may not have 'void' type}}
      a + b; // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('int *' and 'int *')}}
    };

  static_assert(C<int>);
  template<C T> struct C_check {}; // expected-note{{because 'void' does not satisfy 'C'}} expected-note{{because 'int *' does not satisfy 'C'}}
  using c1c1 = C_check<void>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = void]}}
  using c1c2 = C_check<int *>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = int *]}}
}

// typeid() of an expression becomes potentially evaluated if the expression is
// of a polymorphic type.
class X { virtual ~X(); };
constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); };
// expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}}
// expected-note@-2{{'x' declared here}}

namespace access_checks {
namespace in_requires_expression {
template<auto>
struct A {
    static constexpr bool foo();
    static constexpr bool bar();
    static constexpr bool baz();
    static constexpr bool faz();
};

class C{};

class B {
    void p() {}
    bool data_member = true;
    static const bool static_member = true;
    friend struct A<0>;
};

template<auto x>
constexpr bool A<x>::foo() {
    return requires(B b) { b.p(); };
}
static_assert(!A<1>::foo());
static_assert(A<0>::foo());

template<auto x>
constexpr bool A<x>::bar() {
    return requires() { B::static_member; };
}
static_assert(!A<1>::bar());
static_assert(A<0>::bar());

template<auto x>
constexpr bool A<x>::baz() {
    return requires(B b) { b.data_member; };
}
static_assert(!A<1>::baz());
static_assert(A<0>::baz());

template<auto x>
constexpr bool A<x>::faz() {
    return requires(B a, B b) { 
      a.p();
      b.data_member;
      B::static_member;
    };
}
static_assert(!A<1>::faz());
static_assert(A<0>::faz());
} // namespace in_requires_expression

namespace in_concepts {
// Dependent access does not cause hard errors.
template<int N> class A;

template <> class A<0> {
  static void f() {}
};
template<int N>
concept C1 = requires() { A<N>::f(); };
static_assert(!C1<0>);

template <> class A<1> {
public: 
  static void f() {}
};
static_assert(C1<1>);

// Non-dependent access to private member is a hard error.
class B{
   static void f() {} // expected-note 2{{implicitly declared private here}}
};
template<class T>
concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}}

constexpr bool non_template_func() {
  return requires() {
      B::f(); // expected-error {{'f' is a private member}}
  };
}
template<int x>
constexpr bool template_func() {
  return requires() {
      A<x>::f();
  };
}
static_assert(!template_func<0>());
static_assert(template_func<1>());
} // namespace in_concepts

namespace in_trailing_requires {
template <class> struct B;
class A {
   static void f();
   friend struct B<short>;
};
 
template <class T> struct B {
  static constexpr int index() requires requires{ A::f(); } {
    return 1;
  }
  static constexpr int index() {
    return 2;
  }
};

static_assert(B<short>::index() == 1);
static_assert(B<int>::index() == 2);

namespace missing_member_function {
template <class T> struct Use;
class X { 
  int a;
  static int B;
  friend struct Use<short>;
};
template <class T> struct Use {
  constexpr static int foo() requires requires(X x) { x.a; } {
    return 1;
  }
  constexpr static int bar() requires requires { X::B; } {
    return 1;
  }
};

void test() {
  // FIXME: Propagate diagnostic.
  Use<int>::foo(); //expected-error {{invalid reference to function 'foo': constraints not satisfied}}
  static_assert(Use<short>::foo() == 1);
}
} // namespace missing_member_function
} // namespace in_trailing_requires
} // namespace access_check