File: nested-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 (182 lines) | stat: -rw-r--r-- 7,328 bytes parent folder | download | duplicates (8)
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
// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify

static_assert(requires { requires true; });

template<typename T> requires requires { requires false; } // expected-note{{because 'false' evaluated to false}}
struct r1 {};

using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}

template<typename T> requires requires { requires sizeof(T) == 0; } // expected-note{{because 'sizeof(int) == 0' (4 == 0) evaluated to false}}
struct r2 {};

using r2i = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}

template<typename T> requires requires (T t) { requires sizeof(t) == 0; } // expected-note{{because 'sizeof (t) == 0' (4 == 0) evaluated to false}}
struct r3 {};

using r3i = r3<int>; // expected-error{{constraints not satisfied for class template 'r3' [with T = int]}}

template<typename T>
struct X {
    template<typename U> requires requires (U u) { requires sizeof(u) == sizeof(T); } // expected-note{{because 'sizeof (u) == sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}}
    struct r4 {};
};

using r4i = X<void>::r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with U = int]}}

// C++ [expr.prim.req.nested] Examples
namespace std_example {
  template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}}
  template<typename T> concept D =
    requires (T t) {
      requires C1<decltype (+t)>; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}}
  };

  struct T1 { char operator+() { return 'a'; } };
  static_assert(D<T1>);
  template<D T> struct D_check {}; // expected-note{{because 'short' does not satisfy 'D'}}
  using dc1 = D_check<short>; // expected-error{{constraints not satisfied for class template 'D_check' [with T = short]}}

  template<typename T>
  concept C2 = requires (T a) {
      requires sizeof(a) == 4; // OK
      requires a == 0; // expected-note{{because 'a == 0' would be invalid: constraint variable 'a' cannot be used in an evaluated context}}
    };
  static_assert(C2<int>); // expected-note{{because 'int' does not satisfy 'C2'}} expected-error{{static assertion failed}}
}

template<typename T>
concept K = requires (T::Type X) {
  X.next();
};

namespace SubstitutionFailureNestedRequires {
template<class T>  concept True = true;
template<class T>  concept False = false;

struct S { double value; };

template <class T>
concept Pipes = requires (T x) {
   requires True<decltype(x.value)> || True<T> || False<T>;
   requires False<T> || True<T> || True<decltype(x.value)>;
};

template <class T>
concept Amps1 = requires (T x) {
   requires True<decltype(x.value)> && True<T> && !False<T>; // #Amps1
};
template <class T>
concept Amps2 = requires (T x) {
   requires True<T> && True<decltype(x.value)>;
};

static_assert(Pipes<S>);
static_assert(Pipes<double>);

static_assert(Amps1<S>);
static_assert(!Amps1<double>);

static_assert(Amps2<S>);
static_assert(!Amps2<double>);

template<class T>
void foo1() requires requires (T x) { // #foo1
  requires
  True<decltype(x.value)> // #foo1Value
  && True<T>;
} {}
template<class T> void fooPipes() requires Pipes<T> {}
template<class T> void fooAmps1() requires Amps1<T> {} // #fooAmps1
void foo() {
  foo1<S>();
  foo1<int>(); // expected-error {{no matching function for call to 'foo1'}}
  // expected-note@#foo1Value {{because 'True<decltype(x.value)> && True<T>' would be invalid: member reference base type 'int' is not a structure or union}}
  // expected-note@#foo1 {{candidate template ignored: constraints not satisfied [with T = int]}}
  fooPipes<S>();
  fooPipes<int>();
  fooAmps1<S>();
  fooAmps1<int>(); // expected-error {{no matching function for call to 'fooAmps1'}}
  // expected-note@#fooAmps1 {{candidate template ignored: constraints not satisfied [with T = int]}}
  // expected-note@#fooAmps1 {{because 'int' does not satisfy 'Amps1'}}
  // expected-note@#Amps1 {{because 'True<decltype(x.value)> && True<T> && !False<T>' would be invalid: member reference base type 'int' is not a structure or union}}
}

template<class T>
concept HasNoValue = requires (T x) {
  requires !True<decltype(x.value)> && True<T>;
};
// FIXME: 'int' does not satisfy 'HasNoValue' currently since `!True<decltype(x.value)>` is an invalid expression.
// But, in principle, it should be constant-evaluated to true.
// This happens also for requires expression and is not restricted to nested requirement.
static_assert(!HasNoValue<int>);
static_assert(!HasNoValue<S>);

template<class T> constexpr bool NotAConceptTrue = true;
template <class T>
concept SFinNestedRequires = requires (T x) {
    // SF in a non-concept specialisation should also be evaluated to false.
   requires NotAConceptTrue<decltype(x.value)> || NotAConceptTrue<T>;
};
static_assert(SFinNestedRequires<int>);
static_assert(SFinNestedRequires<S>);
template <class T>
void foo() requires SFinNestedRequires<T> {}
void bar() {
  foo<int>();
  foo<S>();
}
namespace ErrorExpressions_NotSF {
template<typename T> struct X { static constexpr bool value = T::value; }; // #X_Value
struct True { static constexpr bool value = true; };
struct False { static constexpr bool value = false; };
template<typename T> concept C = true;
template<typename T> concept F = false;

template<typename T> requires requires(T) { requires C<T> || X<T>::value; } void foo();

template<typename T> requires requires(T) { requires C<T> && X<T>::value; } void bar(); // #bar
template<typename T> requires requires(T) { requires F<T> || (X<T>::value && C<T>); } void baz();

void func() {
  foo<True>();
  foo<False>();
  foo<int>();

  bar<True>();
  bar<False>();
  // expected-error@-1 {{no matching function for call to 'bar'}}
  // expected-note@#bar {{while substituting template arguments into constraint expression here}}
  // expected-note@#bar {{while checking the satisfaction of nested requirement requested here}}
  // expected-note@#bar {{candidate template ignored: constraints not satisfied [with T = False]}}
  // expected-note@#bar {{because 'X<False>::value' evaluated to false}}

  bar<int>();
  // expected-note@-1 {{while checking constraint satisfaction for template 'bar<int>' required here}} \
  // expected-note@-1 {{in instantiation of function template specialization}}
  // expected-note@#bar {{in instantiation of static data member}}
  // expected-note@#bar {{in instantiation of requirement here}}
  // expected-note@#bar {{while checking the satisfaction of nested requirement requested here}}
  // expected-note@#bar {{while substituting template arguments into constraint expression here}}
  // expected-error@#X_Value {{type 'int' cannot be used prior to '::' because it has no members}}
}
}
}

namespace no_crash_D138914 {
// https://reviews.llvm.org/D138914
template <class a, a> struct b;
template <bool c> using d = b<bool, c>;
template <class a, class e> using f = d<__is_same(a, e)>;
template <class a, class e>
concept g = f<a, e>::h;
template <class a, class e>
concept i = g<e, a>;
template <typename> class j {
  template <typename k>
  requires requires { requires i<j, k>; }
  j();
};
template <> j(); // expected-error {{deduction guide declaration without trailing return type}}
}