File: cxx20-ctad-type-alias.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (496 lines) | stat: -rw-r--r-- 13,934 bytes parent folder | download | duplicates (3)
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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-linux -Wno-c++11-narrowing -Wno-literal-conversion -std=c++20 -verify %s

namespace test1 {
template <typename T>
struct Foo { T t; };
template <typename U>
using Bar = Foo<U>;

Bar s = {1};
}  // namespace test1

namespace test2 {
template <typename X, typename Y>
struct XYpair {
  X x;
  Y y;
};
// A tricky explicit deduction guide that swapping X and Y.
template <typename X, typename Y>
XYpair(X, Y) -> XYpair<Y, X>;
template <typename U, typename V>
using AliasXYpair = XYpair<U, V>;

AliasXYpair xy = {1.1, 2};  // XYpair<int, double>
static_assert(__is_same(decltype(xy.x), int));
static_assert(__is_same(decltype(xy.y), double));
}  // namespace test2

namespace test3 {
template <typename T, class>
struct container {
  // test with default arguments.
  container(T a, T b = T());
};

template <class T>
using vector = container<T, int>;
vector v(0, 0);
}  // namespace test3

namespace test4 {
// Explicit deduction guide.
template <class T>
struct X {
  T t;
  X(T);
};

template <class T>
X(T) -> X<double>;

template <class T>
using AX = X<T>;

AX s = {1};
static_assert(__is_same(decltype(s.t), double)); // explicit one is picked.
}  // namespace test4

namespace test5 {
template <int B>
struct Foo {};
// Template parameter pack
template <int... C>
using AF = Foo<1>;
auto a = AF{};
}  // namespace test5

namespace test6 {
// non-type template argument.
template <typename T, bool B = false>
struct Foo {
  Foo(T);
};
template <typename T>
using AF = Foo<T, 1>;

AF b{0};
}  // namespace test6

namespace test7 {
template <typename T>
struct Foo {
  Foo(T);
};
// using alias chain.
template <typename U>
using AF1 = Foo<U>;
template <typename K>
using AF2 = AF1<K>;
AF2 b = 1;
}  // namespace test7

namespace test8 {
template <typename T, int N>
struct Foo {
  Foo(T const (&)[N]);
};

template <typename X, int Y>
using Bar = Foo<X, Y>;

Bar s = {{1}};
}  // namespace test8

namespace test9 {
template <typename T, int N>
struct Foo {
  Foo(T const (&)[N]);
};

template <typename X, int Y>
using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \
                               // expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, sizeof(X)>) Bar(Foo<X, sizeof(X)>) -> Foo<X, sizeof(X)>'}} \
                               // expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, sizeof(X)>) Bar(const X (&)[sizeof(X)]) -> Foo<X, sizeof(X)>'}} \
                               // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \
                               // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo<int, 4UL>'}}


Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }}
}  // namespace test9

namespace test10 {
template <typename T>
struct Foo {
  template <typename U>
  Foo(U);
};

template <typename U>
Foo(U) -> Foo<U*>;

template <typename K>
using A = Foo<K>;
A a(2);  // Foo<int*>
}  // namespace test10

namespace test11 {
struct A {};
template<class T> struct Foo { T c; };
template<class X, class Y=A>
using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not match 'Foo<Y>' against 'int'}} \
                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo(Foo<Y>) -> Foo<Y>'}} \
                    // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \
                    // expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo<int>'}} \
                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo(Y) -> Foo<Y>'}} \
                    // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} \
                    // expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo() -> Foo<Y>'}}

AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}}
} // namespace test11

namespace test12 {
// no crash on null access attribute
template<typename X>
struct Foo {
  template<typename K>
  struct Bar {
    Bar(K);
  };

  template<typename U>
  using ABar = Bar<U>;
  void test() { ABar k = 2; }
};

void func(Foo<int> s) {
  s.test();
}
} // namespace test12

namespace test13 {
template <typename... Ts>
struct Foo {
  Foo(Ts...);
};

template <typename... Ts>
using AFoo = Foo<Ts...>;

auto b = AFoo{};
AFoo a(1, 2);

template <typename T>
using BFoo = Foo<T, T>;
BFoo b2(1.0, 2.0);
} // namespace test13

namespace test14 {
template<typename T>
concept IsInt = __is_same(decltype(T()), int);

template<IsInt T, int N>
struct Foo {
  Foo(T const (&)[N]);
};

template <int K>
using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for class template 'Foo'}}
// expected-note@-1 {{candidate template ignored: could not match}}
// expected-note@-2 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(Foo<double, K>) -> Foo<double, K>'}}
// expected-note@-3 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(const double (&)[K]) -> Foo<double, K>'}}
double abc[3];
Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide for deduction }}
} // namespace test14

namespace test15 {
template <class T> struct Foo { Foo(T); };

template<class V> using AFoo = Foo<V *>;
template<typename> concept False = false;
template<False W>
using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
                      // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
                      // expected-note {{implicit deduction guide declared as 'template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(V *) -> Foo<V *>}} \
                      // expected-note {{candidate template ignored: could not match 'Foo<V *>' against 'int *'}} \
                      // expected-note {{template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(Foo<V *>) -> Foo<V *>}}
int i = 0;
AFoo a1(&i); // OK, deduce Foo<int *>

// the W is not deduced from the deduced type Foo<int *>.
BFoo b2(&i); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'BFoo'}}
} // namespace test15

namespace test16 {
struct X { X(int); X(const X&); };
template<class T>
struct Foo {
  T t;
  Foo(T t) : t(t) {}
};
template<class T>
using AFoo = Foo<T>;
int i = 0;
AFoo s{i};
static_assert(__is_same(decltype(s.t), int));

// explicit deduction guide.
Foo(int) -> Foo<X>;
AFoo s2{i};
// FIXME: the type should be X because of the above explicit deduction guide.
static_assert(__is_same(decltype(s2.t), int));
} // namespace test16

namespace test17 {
template <typename T>
struct Foo { T t; };

// CTAD for alias templates only works for the RHS of the alias of form of
//  [typename] [nested-name-specifier] [template] simple-template-id
template <typename U>
using AFoo = Foo<U>*; // expected-note {{template is declared here}}

AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}}
} // namespace test17

namespace test18 {
template<typename T>
concept False = false; // expected-note {{because 'false' evaluated to false}}

template <typename T> struct Foo { T t; };

template<typename T> requires False<T> // expected-note {{because 'int' does not satisfy 'False'}}
Foo(T) -> Foo<int>;

template <typename U>
using Bar = Foo<U>; // expected-note {{could not match 'Foo<U>' against 'int'}} \
                    // expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar(Foo<U>) -> Foo<U>'}} \
                    // expected-note {{candidate template ignored: constraints not satisfied}} \
                    // expected-note {{implicit deduction guide declared as 'template <typename T> requires False<T> && __is_deducible(test18::Bar, Foo<int>) Bar(T) -> Foo<int>'}} \
                    // expected-note {{candidate function template not viable}} \
                    // expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar() -> Foo<U>'}}

Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
} // namespace test18

// GH85406, verify no crash on invalid alias templates.
namespace test19 {
template <typename T>
class Foo {};

template <typename T>
template <typename K>
using Bar2 = Foo<K>; // expected-error {{extraneous template parameter list in alias template declaration}}

Bar2 b = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
} // namespace test19

// GH85385
namespace test20 {
template <template <typename> typename T>
struct K {};

template <typename U>
class Foo {};

// Verify that template template type parameter TTP is referenced/used in the
// template arguments of the RHS.
template <template<typename> typename TTP>
using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<TTP>>' against 'int'}} \
                        // expected-note {{implicit deduction guide declared as 'template <template <typename> typename TTP> requires __is_deducible(test20::Bar, Foo<K<TTP>>) Bar(Foo<K<TTP>>) -> Foo<K<TTP>>'}}

template <class T>
class Container {};
Bar t = Foo<K<Container>>();

Bar s = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of}}
} // namespace test20

namespace test21 {
template <typename T, unsigned N>
struct Array { const T member[N]; };
template <unsigned N>
using String = Array<char, N>;

// Verify no crash on constructing the aggregate deduction guides.
String s("hello");
} // namespace test21

// GH89013
namespace test22 {
class Base {};
template <typename T>
class Derived final : public Base {};

template <typename T, typename D>
requires __is_base_of(Base, D)
struct Foo {
  explicit Foo(D) {}
};

template <typename U>
using AFoo = Foo<int, Derived<U>>;

AFoo a(Derived<int>{});
} // namespace test22

namespace test23 {
// We have an aggregate deduction guide "G(T) -> G<T>".
template<typename T>
struct G { T t1; };

template<typename X = int>
using AG = G<int>;

AG ag(1.0);
// Verify that the aggregate deduction guide "AG(int) -> AG<int>" is built and
// choosen.
static_assert(__is_same(decltype(ag.t1), int));
} // namespace test23

// GH90177
// verify that the transformed require-clause of the alias deduction gudie has
// the right depth info.
namespace test24 {
class Forward;
class Key {};

template <typename D>
constexpr bool C = sizeof(D);

// Case1: the alias template and the underlying deduction guide are in the same
// scope.
template <typename T>
struct Case1 {
  template <typename U>
  struct Foo {
    Foo(U);
  };

  template <typename V>
  requires (C<V>)
  Foo(V) -> Foo<V>;

  template <typename Y>
  using Alias = Foo<Y>;
};
// The require-clause should be evaluated on the type Key.
Case1<Forward>::Alias t2 = Key();


// Case2: the alias template and underlying deduction guide are in different
// scope.
template <typename T>
struct Foo {
  Foo(T);
};
template <typename U>
requires (C<U>)
Foo(U) -> Foo<U>;

template <typename T>
struct Case2 {
  template <typename Y>
  using Alias = Foo<Y>;
};
// The require-caluse should be evaluated on the type Key.
Case2<Forward>::Alias t1 = Key();

// Case3: crashes on the constexpr evaluator due to the mixed-up depth in
// require-expr.
template <class T1>
struct A1 {
  template<class T2>
  struct A2 {
    template <class T3>
    struct Foo {
      Foo(T3);
    };
    template <class T3>
    requires C<T3>
    Foo(T3) -> Foo<T3>;
  };
};
template <typename U>
using AFoo = A1<int>::A2<int>::Foo<U>;
AFoo case3(1);

// Case4: crashes on the constexpr evaluator due to the mixed-up index for the
// template parameters `V`.
template<class T, typename T2>
struct Case4 {
  template<class V> requires C<V>
  Case4(V, T);
};

template<class T2>
using ACase4 = Case4<T2, T2>;
ACase4 case4{0, 1};

} // namespace test24

namespace GH92212 {
template<typename T, typename...Us>
struct A{
  template<typename V> requires __is_same(V, int)
  A(V);
};

template<typename...TS>
using AA = A<int, TS...>;
AA a{0};
}

namespace GH94927 {
template <typename T>
struct A {
  A(T);
};
A(int) -> A<char>;

template <typename U>
using B1 = A<U>;
B1 b1(100); // deduce to A<char>;
static_assert(__is_same(decltype(b1), A<char>));

template <typename U>
requires (!__is_same(U, char)) // filter out the explicit deduction guide.
using B2 = A<U>;
template <typename V>
using B3 = B2<V>;

B2 b2(100); // deduced to A<int>;
static_assert(__is_same(decltype(b2), A<int>));
B3 b3(100); // decuded to A<int>;
static_assert(__is_same(decltype(b3), A<int>));


// the nested case
template <typename T1>
struct Out {
  template <typename T2>
  struct A {
    A(T2);
  };
  A(int) -> A<T1>;
  
  template <typename T3>
  using B = A<T3>;
};

Out<float>::B out(100); // deduced to Out<float>::A<float>;
static_assert(__is_same(decltype(out), Out<float>::A<float>));
}

namespace GH111508 {

template <typename V> struct S {
  using T = V;
  T Data;
};

template <typename V> using Alias = S<V>;

Alias A(42);

} // namespace GH111508