xref: /llvm-project/clang/test/SemaTemplate/concepts-out-of-line-def.cpp (revision 27c917307563eae93c7fef9c3944e56e1f5b5f6d)
1 // RUN: %clang_cc1 -std=c++20 -verify %s
2 
3 static constexpr int PRIMARY = 0;
4 static constexpr int SPECIALIZATION_CONCEPT = 1;
5 static constexpr int SPECIALIZATION_REQUIRES = 2;
6 
7 template <class T>
8 concept Concept = (sizeof(T) >= 2 * sizeof(int));
9 
10 struct XY {
11   int x;
12   int y;
13 };
14 
15 namespace members {
16 
17 template <class T, class U> struct S {
18   static constexpr int primary();
19 };
20 
21 template <class T, class U> constexpr int S<T, U>::primary() {
22   return PRIMARY;
23 };
24 
25 template <Concept C, class U> struct S<C, U> {
26   static constexpr int specialization();
27 };
28 
29 template <class T, class U>
30   requires(sizeof(T) == sizeof(int))
31 struct S<T, U> {
32   static constexpr int specialization();
33 };
34 
35 template <Concept C, class U> constexpr int S<C, U>::specialization() {
36   return SPECIALIZATION_CONCEPT;
37 }
38 
39 template <class T, class U>
40   requires(sizeof(T) == sizeof(int))
41 constexpr int S<T, U>::specialization() {
42   return SPECIALIZATION_REQUIRES;
43 }
44 
45 static_assert(S<char, double>::primary() == PRIMARY);
46 static_assert(S<XY, double>::specialization() == SPECIALIZATION_CONCEPT);
47 static_assert(S<int, double>::specialization() == SPECIALIZATION_REQUIRES);
48 
49 } // namespace members
50 
51 namespace enumerations {
52 
53 template <class T, class U> struct S {
54   enum class E : int;
55 };
56 
57 template <class T, class U> enum class S<T, U>::E { Value = PRIMARY };
58 
59 template <Concept C, class U> struct S<C, U> {
60   enum class E : int;
61 };
62 
63 template <Concept C, class U>
64 enum class S<C, U>::E {
65   Value = SPECIALIZATION_CONCEPT
66 };
67 
68 template <class T, class U>
69   requires(sizeof(T) == sizeof(int))
70 struct S<T, U> {
71   enum class E : int;
72 };
73 
74 template <class T, class U>
75   requires(sizeof(T) == sizeof(int))
76 enum class S<T, U>::E {
77   Value = SPECIALIZATION_REQUIRES
78 };
79 
80 static_assert(static_cast<int>(S<char, double>::E::Value) == PRIMARY);
81 static_assert(static_cast<int>(S<XY, double>::E::Value) ==
82               SPECIALIZATION_CONCEPT);
83 static_assert(static_cast<int>(S<int, double>::E::Value) ==
84               SPECIALIZATION_REQUIRES);
85 
86 } // namespace  enumerations
87 
88 namespace multiple_template_parameter_lists {
89 
90 template <class Outer>
91 struct S {
92   template <class Inner>
93   static constexpr int primary(Inner);
94 };
95 
96 template <class Outer>
97 template <class Inner>
98 constexpr int S<Outer>::primary(Inner) {
99   return PRIMARY;
100 };
101 
102 template <Concept Outer>
103 struct S<Outer> {
104   template <class Inner>
105   static constexpr int specialization(Inner);
106 };
107 
108 template <Concept Outer>
109 template <class Inner>
110 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_CONCEPT; }
111 
112 template <class Outer>
113   requires(sizeof(Outer) == sizeof(int))
114 struct S<Outer> {
115   template <class Inner>
116   static constexpr int specialization(Inner);
117 };
118 
119 template <class Outer>
120   requires(sizeof(Outer) == sizeof(int))
121 template <class Inner>
122 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_REQUIRES; }
123 
124 static_assert(S<char>::primary("str") == PRIMARY);
125 static_assert(S<XY>::specialization("str") == SPECIALIZATION_CONCEPT);
126 static_assert(S<int>::specialization("str") == SPECIALIZATION_REQUIRES);
127 
128 } // namespace multiple_template_parameter_lists
129 
130 static constexpr int CONSTRAINED_METHOD_1 = 1;
131 static constexpr int CONSTRAINED_METHOD_2 = 2;
132 
133 namespace constrained_members {
134 
135 template <int>
136 struct S {
137   template <Concept C>
138   static constexpr int constrained_method();
139 };
140 
141 template <>
142 template <Concept C>
143 constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
144 
145 template <>
146 template <Concept C>
147 constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
148 
149 static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
150 static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
151 
152 
153 template <class T1, class T2>
154 concept ConceptT1T2 = true;
155 
156 template<typename T3>
157 struct S12 {
158   template<ConceptT1T2<T3> T4>
159   static constexpr int constrained_method();
160 };
161 
162 template<>
163 template<ConceptT1T2<int> T5>
164 constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; }
165 
166 template<>
167 template<ConceptT1T2<double> T5>
168 constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; }
169 
170 static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
171 static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
172 
173 } // namespace constrained members
174 
175 namespace constrained_members_of_nested_types {
176 
177 template <int>
178 struct S {
179   struct Inner0 {
180     struct Inner1 {
181       template <Concept C>
182       static constexpr int constrained_method();
183     };
184   };
185 };
186 
187 template <>
188 template <Concept C>
189 constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
190 
191 template <>
192 template <Concept C>
193 constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
194 
195 static_assert(S<1>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
196 static_assert(S<2>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
197 
198 
199 template <class T1, class T2>
200 concept ConceptT1T2 = true;
201 
202 template<typename T3>
203 struct S12 {
204   struct Inner0 {
205     struct Inner1 {
206       template<ConceptT1T2<T3> T4>
207       static constexpr int constrained_method();
208     };
209   };
210 };
211 
212 template<>
213 template<ConceptT1T2<int> T5>
214 constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
215 
216 template<>
217 template<ConceptT1T2<double> T5>
218 constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
219 
220 static_assert(S12<int>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
221 static_assert(S12<double>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
222 
223 } // namespace constrained_members_of_nested_types
224 
225 namespace constrained_member_sfinae {
226 
227 template<int N> struct S {
228   template<class T>
229   static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) { // expected-warning {{variable length arrays in C++ are a Clang extension}} \
230                                                                                                   expected-note {{value 4294967296 is outside the range of representable values of type 'int'}} \
231                                                                                                   expected-note {{while calculating associated constraint of template 'constrained_method' here}}
232     return CONSTRAINED_METHOD_1;
233   }
234 
235   template<class T>
236   static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
237 };
238 
239 template<>
240 template<typename T>
241 constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
242   return CONSTRAINED_METHOD_2;
243 }
244 
245 // Verify that there is no amiguity in this case.
246 static_assert(S<4>::constrained_method<double>() == CONSTRAINED_METHOD_2);
247 
248 } // namespace constrained_member_sfinae
249 
250 namespace requires_expression_references_members {
251 
252 void accept1(int x);
253 void accept2(XY xy);
254 
255 template <class T> struct S {
256   T Field = T();
257 
258   constexpr int constrained_method()
259       requires requires { accept1(Field); };
260 
261   constexpr int constrained_method()
262       requires requires { accept2(Field); };
263 };
264 
265 template <class T>
266 constexpr int S<T>::constrained_method()
267   requires requires { accept1(Field); } {
268   return CONSTRAINED_METHOD_1;
269 }
270 
271 template <class T>
272 constexpr int S<T>::constrained_method()
273   requires requires { accept2(Field); } {
274   return CONSTRAINED_METHOD_2;
275 }
276 
277 static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1);
278 static_assert(S<XY>().constrained_method() == CONSTRAINED_METHOD_2);
279 
280 } // namespace requires_expression_references_members
281 
282 namespace GH60231 {
283 
284 template<typename T0> concept C = true;
285 
286 template <typename T1>
287 struct S {
288   template <typename F1> requires C<S<T1>>
289   void foo1(F1 f);
290 
291   template <typename F2>
292   void foo2(F2 f) requires C<S<T1>>;
293 
294   template <typename F3> requires C<F3>
295   void foo3(F3 f);
296 };
297 
298 template <typename T2>
299 template <typename F4> requires C<S<T2>>
300 void S<T2>::foo1(F4 f) {}
301 
302 template <typename T3>
303 template <typename F5>
304 void S<T3>::foo2(F5 f) requires C<S<T3>> {}
305 
306 template <typename T4>
307 template <typename F6> requires C<F6>
308 void S<T4>::foo3(F6 f) {}
309 
310 } // namespace GH60231
311 
312 namespace GH62003 {
313 
314 template <typename T0> concept Concept = true;
315 
316 template <class T1>
317 struct S1 {
318   template <Concept C1>
319   static constexpr int foo();
320 };
321 template <class T2>
322 template <Concept C2>
323 constexpr int S1<T2>::foo() { return 1; }
324 
325 template <Concept C3>
326 struct S2 {
327   template <class T3>
328   static constexpr int foo();
329 };
330 template <Concept C4>
331 template <class T4>
332 constexpr int S2<C4>::foo() { return 2; }
333 
334 template <Concept C5>
335 struct S3 {
336   template <Concept C6>
337   static constexpr int foo();
338 };
339 template <Concept C7>
340 template <Concept C8>
341 constexpr int S3<C7>::foo() { return 3; }
342 
343 static_assert(S1<int>::foo<int>() == 1);
344 static_assert(S2<int>::foo<int>() == 2);
345 static_assert(S3<int>::foo<int>() == 3);
346 
347 } // namespace GH62003
348 
349 namespace MultilevelTemplateWithPartialSpecialization {
350 template <typename>
351 concept Concept = true;
352 
353 namespace two_level {
354 template <typename T1, int>
355 struct W0 {
356   template <typename T2>
357   requires (Concept<T2>)
358   void f(const T2 &);
359 };
360 
361 template <typename T3>
362 struct W0<T3, 0> {
363   template <typename T4>
364   requires (Concept<T4>)
365   void f(const T4 &);
366 };
367 
368 template <typename T3>
369 template <typename T4>
370 requires (Concept<T4>)
371 inline void W0<T3, 0>::f(const T4 &) {}
372 } // namespace two_level
373 
374 namespace three_level {
375 template <typename T1, int>
376 struct W0 {
377   template <typename T2>
378   struct W1 {
379     template <typename T3>
380     requires (Concept<T3>)
381     void f(const T3 &);
382   };
383 };
384 
385 template <typename T4>
386 struct W0<T4, 0> {
387   template <typename T5>
388   struct W1 {
389     template <typename T6>
390     requires (Concept<T6>)
391     void f(const T6 &);
392   };
393 };
394 
395 template <typename T7>
396 template <typename T8>
397 template <typename T9>
398 requires (Concept<T9>)
399 inline void W0<T7, 0>::W1<T8>::f(const T9 &) {}
400 } // namespace three_level
401 
402 } // namespace MultilevelTemplateWithPartialSpecialization
403 
404 namespace PR62697 {
405 template<typename>
406 concept c = true;
407 
408 template<typename T>
409 struct s {
410     void f() requires c<void(T)>;
411 };
412 
413 template<typename T>
414 void s<T>::f() requires c<void(T)> { }
415 }
416 
417 namespace GH62272 {
418 template<typename T> concept A = true;
419 template<typename T> struct X { A<T> auto f(); };
420 template<typename T> A<T> auto X<T>::f() {}
421 }
422 
423 namespace GH65810 {
424 template<typename Param>
425 concept TrivialConcept =
426 requires(Param param) {
427   (void)param;
428 };
429 
430 template <typename T>
431 struct Base {
432   class InnerClass;
433 };
434 
435 template <typename T>
436 class Base<T>::InnerClass {
437   template <typename Param>
438     requires TrivialConcept<Param>
439     int func(Param param) const;
440 };
441 
442 template <typename T>
443 template <typename Param>
444 requires TrivialConcept<Param>
445 int Base<T>::InnerClass::func(Param param) const {
446   return 0;
447 }
448 
449 template<typename T>
450 struct Outermost {
451   struct Middle {
452     template<typename U>
453     struct Innermost {
454       template <typename Param>
455         requires TrivialConcept<Param>
456         int func(Param param) const;
457     };
458   };
459 };
460 
461 template <typename T>
462 template <typename U>
463 template <typename Param>
464 requires TrivialConcept<Param>
465 int Outermost<T>::Middle::Innermost<U>::func(Param param) const {
466   return 0;
467 }
468 
469 } // namespace GH65810
470 
471 namespace GH61763 {
472 template<typename T, typename U>
473 concept same_as = true;
474 
475 template <class = void>
476 struct Foo {
477       template <same_as<void> Param>
478             friend struct Bar;
479 };
480 
481 template struct Foo<>;
482 
483 template <same_as<void> Param>
484 struct Bar {
485 };
486 
487 
488 template<typename T>
489 concept ok = true;
490 
491 struct outer {
492     template<typename T>
493         requires ok<T>
494           struct foo {};
495 };
496 
497 template<typename U>
498 struct bar {
499     template<typename T>
500         requires ok<T>
501           friend struct outer::foo;
502 };
503 
504 bar<int> x;
505 } // namespace GH61763
506 
507 
508 namespace GH74314 {
509 template <class T, class U> constexpr bool is_same_v = __is_same(T, U);
510 template <class T, class U> constexpr bool is_not_same_v = !__is_same(T, U);
511 
512 template <class Result>
513 concept something_interesting = requires {
514       true;
515       requires is_same_v<int, Result>;
516 };
517 
518 template <class T>
519 struct X { // #defined-here
520       void foo() requires requires { requires is_not_same_v<T, int>; };
521       void bar(decltype(requires { requires is_not_same_v<T, int>; }));
522 };
523 
524 template <class T>
525 void X<T>::foo() requires requires { requires something_interesting<T>; } {}
526 // expected-error@-1{{definition of 'foo' does not match any declaration}}
527 // expected-note@#defined-here{{defined here}}
528 // expected-note@-8{{member declaration nearly matches}}
529 
530 template <class T>
531 void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok
532 
533 template <class T>
534 void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
535 // expected-error@-1{{definition of 'bar' does not match any declaration}}
536 // expected-note@#defined-here{{defined here}}
537 
538 template <class T>
539 void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
540 } // namespace GH74314
541 
542 namespace GH56482 {
543 template <typename SlotMap>
544 concept slot_map_has_reserve = true;
545 
546 template <typename T> struct Slot_map {
547   constexpr void reserve() const noexcept
548     requires slot_map_has_reserve<Slot_map>;
549 
550   constexpr void reserve(int) const noexcept
551     requires slot_map_has_reserve<Slot_map<T>>;
552 };
553 
554 template <typename T>
555 constexpr void Slot_map<T>::reserve() const noexcept
556   requires slot_map_has_reserve<Slot_map<T>>
557 {}
558 
559 template <typename T>
560 constexpr void Slot_map<T>::reserve(int) const noexcept
561   requires slot_map_has_reserve<Slot_map>
562 {}
563 } // namespace GH56482
564 
565 namespace GH74447 {
566 template <typename T> struct S {
567   template <typename... U, int V>
568   void test(T target, U... value)
569     requires requires {
570       target;
571       sizeof...(value) == 1;
572       V == 2;
573     };
574 };
575 
576 template <typename T>
577 template <typename... U, int V>
578 void S<T>::test(T target, U... value)
579   requires requires {
580     target;
581     sizeof...(value) == 1;
582     V == 2;
583   }
584 {}
585 } // namespace GH74447
586 
587 namespace GH72557 {
588 
589 template <typename...>
590 concept IsAnyOf = true;
591 
592 template <class... DerTs> struct DerivedCollection {
593   template <class DerT>
594     requires IsAnyOf<DerTs...>
595   unsigned long index();
596 };
597 
598 template <class... DerTs>
599 template <class DerT>
600   requires IsAnyOf<DerTs...>
601 unsigned long DerivedCollection<DerTs...>::index() {}
602 
603 } // namespace GH72557
604 
605 namespace GH101735 {
606 
607 template <class, class>
608 concept True = true;
609 
610 template <typename T>
611 class A {
612   template <typename... Ts>
613   void method(Ts&... ts)
614     requires requires (T t) {
615       { t.method(static_cast<Ts &&>(ts)...) } -> True<void>;
616     };
617 };
618 
619 template <typename T>
620 template <typename... Ts>
621 void A<T>::method(Ts&... ts)
622   requires requires (T t) {
623     { t.method(static_cast<Ts &&>(ts)...) } -> True<void>;
624   } {}
625 
626 }
627 
628 namespace GH63782 {
629 // GH63782 was also fixed by PR #80594, so let's add a test for it.
630 
631 template<bool... Vals>
632 constexpr bool All = (Vals && ...);
633 
634 template<bool... Bs>
635 class Class {
636   template<typename>
637   requires All<Bs...>
638   void Foo();
639 };
640 
641 template<bool... Bs>
642 template<typename>
643 requires All<Bs...>
644 void Class<Bs...>::Foo() {
645 };
646 
647 } // namespace GH63782
648 
649 namespace eve {
650 // Reduced from the "eve" project
651 
652 template <typename... Ts>
653 struct tuple {
654   template <int I0> requires(I0 <= sizeof...(Ts))
655   constexpr auto split();
656 };
657 
658 template <typename... Ts>
659 template <int I0>
660 requires(I0 <= sizeof...(Ts))
661 constexpr auto tuple<Ts...>::split(){
662   return 0;
663 }
664 
665 int foo() {
666   tuple<int, float> x;
667   return x.split<0>();
668 }
669 
670 } // namespace eve
671 
672 namespace GH93099 {
673 
674 // Issues with sizeof...(expr)
675 
676 template <typename T = int> struct C {
677   template <int... N>
678     requires(sizeof...(N) > 0)
679   friend class NTTP;
680 
681   template <class... Tp>
682     requires(sizeof...(Tp) > 0)
683   friend class TP;
684 
685   template <template <typename> class... TTp>
686     requires(sizeof...(TTp) > 0)
687   friend class TTP;
688 };
689 
690 template <int... N>
691   requires(sizeof...(N) > 0)
692 class NTTP;
693 
694 template <class... Tp>
695   requires(sizeof...(Tp) > 0)
696 class TP;
697 
698 template <template <typename> class... TTp>
699   requires(sizeof...(TTp) > 0)
700 class TTP;
701 
702 C v;
703 
704 } // namespace GH93099
705 
706 namespace GH115098 {
707 
708 template <typename... Ts> struct c {
709   template <typename T>
710     requires(sizeof...(Ts) > 0)
711   friend bool operator==(c, c);
712 };
713 
714 template <typename... Ts> struct d {
715   template <typename T>
716     requires(sizeof...(Ts) > 0)
717   friend bool operator==(d, d);
718 };
719 
720 template struct c<int>;
721 template struct d<int, int>;
722 
723 } // namespace GH115098
724 
725 namespace GH123441 {
726 
727 struct buf {
728   constexpr buf(auto&&... initList) requires (sizeof...(initList) <= 8);
729 };
730 
731 constexpr buf::buf(auto&&... initList) requires (sizeof...(initList) <= 8) {}
732 
733 template <class>
734 struct buffer {
735   constexpr buffer(auto&&... initList) requires (sizeof...(initList) <= 8);
736 };
737 
738 template <class T>
739 constexpr buffer<T>::buffer(auto&&... initList) requires (sizeof...(initList) <= 8) {}
740 
741 template <class...>
742 struct foo { // expected-note {{foo defined here}}
743   constexpr foo(auto&&... initList)
744     requires (sizeof...(initList) <= 8);
745 };
746 
747 template <class... T>
748 constexpr foo<T...>::foo(auto&&... initList) // expected-error {{does not match any declaration}}
749   requires (sizeof...(T) <= 8) {}
750 
751 } // namespace GH123441
752 
753 namespace GH114685 {
754 
755 template <typename T> struct ptr {
756   template <typename U>
757   friend ptr<U> make_item(auto &&args)
758     requires(sizeof(args) > 1);
759 };
760 
761 template <typename U>
762 ptr<U> make_item(auto &&args)
763   requires(sizeof(args) > 1) {}
764 
765 ptr<char> p;
766 
767 } // namespace GH114685
768 
769 namespace GH123472 {
770 
771 consteval bool fn() { return true; }
772 
773 struct S {
774   template <typename T>
775   static consteval void mfn() requires (bool(&fn));
776 };
777 
778 template <typename T>
779 consteval void S::mfn() requires (bool(&fn)) {}
780 
781 }
782