1 // RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s
3 template<typename T
> concept C1
= true; // expected-note{{template is declared here}}
4 static_assert(C1
<int>);
6 // expected-error@-1{{use of concept 'C1' requires template arguments}}
8 template<typename T
> concept C2
= sizeof(T
) == 4;
9 static_assert(C2
<int>);
10 static_assert(!C2
<long long int>);
11 static_assert(C2
<char[4]>);
12 static_assert(!C2
<char[5]>);
14 template<typename T
> concept C3
= sizeof(*T
{}) == 4;
15 static_assert(C3
<int*>);
16 static_assert(!C3
<long long int>);
19 static constexpr int add(int a
, int b
) {
24 static int add(int a
, int b
) { // expected-note{{declared here}}
29 concept C4
= U::add(1, 2) == 3;
30 // expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}}
31 // expected-note@-2{{non-constexpr function 'add' cannot be used in a constant expression}}
33 static_assert(!C4
<B
>); // expected-note {{while checking the satisfaction of concept 'C4<B>' requested here}}
35 template<typename T
, typename U
>
36 constexpr bool is_same_v
= false;
39 constexpr bool is_same_v
<T
, T
> = true;
41 template<typename T
, typename U
>
42 concept Same
= is_same_v
<T
, U
>;
44 static_assert(Same
<int, int>);
45 static_assert(Same
<int, decltype(1)>);
46 static_assert(!Same
<int, unsigned int>);
47 static_assert(!Same
<A
, B
>);
48 static_assert(Same
<A
, A
>);
50 static_assert(Same
<bool, decltype(C1
<int>)>);
51 static_assert(Same
<bool, decltype(C2
<int>)>);
52 static_assert(Same
<bool, decltype(C3
<int*>)>);
53 static_assert(Same
<bool, decltype(C4
<A
>)>);
55 template<typename T
> concept C5
= T
{}; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
56 constexpr bool x
= C5
<int>; // expected-note {{while checking the satisfaction of concept 'C5<int>' requested here}}
59 concept IsEven
= (x
% 2) == 0;
61 static_assert(IsEven
<20>);
62 static_assert(!IsEven
<11>);
64 template<template<typename T
> typename P
>
65 concept IsTypePredicate
= is_same_v
<decltype(P
<bool>::value
), const bool>
66 && is_same_v
<decltype(P
<int>::value
), const bool>
67 && is_same_v
<decltype(P
<long long>::value
), const bool>;
69 template<typename T
> struct T1
{};
70 template<typename T
> struct T2
{ static constexpr bool value
= sizeof(T
) == 2; };
72 static_assert(IsTypePredicate
<T2
>);
73 static_assert(!IsTypePredicate
<T1
>);
75 template<typename T
, typename U
, typename
... Ts
>
76 concept OneOf
= (Same
<T
, Ts
> || ...);
78 static_assert(OneOf
<int, long, int>);
79 static_assert(!OneOf
<long, int, char, char>);
81 namespace piecewise_substitution
{
86 concept A
= True
<T
> || T::value
;
89 concept B
= (True
<T
> || T::value
);
92 concept C
= !True
<T
> && T::value
|| true;
95 concept D
= (!True
<T
> && T::value
) || true;
98 concept E
= T::value
|| True
<T
>;
100 template <typename T
>
101 concept F
= (T::value
|| True
<T
>);
103 template <typename T
>
104 concept G
= T::value
&& !True
<T
> || true;
106 template <typename T
>
107 concept H
= (T::value
&& !True
<T
>) || true;
109 template <typename T
>
110 concept I
= T::value
;
112 static_assert(A
<int>);
113 static_assert(B
<int>);
114 static_assert(C
<int>);
115 static_assert(D
<int>);
116 static_assert(E
<int>);
117 static_assert(F
<int>);
118 static_assert(G
<int>);
119 static_assert(H
<int>);
120 static_assert(!I
<int>);
125 template<typename T
> struct T3
{ using type
= typename
T::type
; };
126 // expected-error@-1{{type 'char' cannot be used prior to '::' because it has no members}}
127 // expected-error@-2{{type 'short' cannot be used prior to '::' because it has no members}}
130 concept C6
= sizeof(T
) == 1 && sizeof(typename T3
<T
>::type
) == 1;
131 // expected-note@-1{{while substituting template arguments into constraint expression here}}
132 // expected-note@-2{{in instantiation of template class 'T3<char>' requested here}}
135 concept C7
= sizeof(T
) == 1 || sizeof(
136 // expected-note@-1{{while substituting template arguments into constraint expression here}}
139 // expected-note@-1{{in instantiation of template class 'T3<short>' requested here}}
142 static_assert(!C6
<short>);
143 static_assert(!C6
<char>); // expected-note{{while checking the satisfaction of concept 'C6<char>' requested here}}
144 static_assert(C7
<char>);
145 static_assert(!C7
<short>); // expected-note{{while checking the satisfaction of concept 'C7<short>' requested here}}
147 // Make sure argument list is converted when instantiating a CSE.
149 template<typename T
, typename U
= int>
150 concept SameSize
= sizeof(T
) == sizeof(U
);
153 struct X
{ static constexpr bool a
= SameSize
<T
>; };
155 static_assert(X
<unsigned>::a
);
157 // static_assert concept diagnostics
159 concept Large
= sizeof(T
) > 100;
160 // expected-note@-1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}}
163 static_assert(Large
<small
>);
164 // expected-error@-1 {{static_assert failed}}
165 // expected-note@-2 {{because 'small' does not satisfy 'Large'}}
166 static_assert(Large
<small
>, "small isn't large");
167 // expected-error@-1 {{static_assert failed "small isn't large"}}
168 // expected-note@-2 {{because 'small' does not satisfy 'Large'}}
170 // Make sure access-checking can fail a concept specialization
172 class T4
{ static constexpr bool f
= true; };
173 template<typename T
> concept AccessPrivate
= T
{}.f
;
174 // expected-note@-1{{because substituted constraint expression is ill-formed: 'f' is a private member of 'T4'}}
175 static_assert(AccessPrivate
<T4
>);
176 // expected-error@-1{{static_assert failed}}
177 // expected-note@-2{{because 'T4' does not satisfy 'AccessPrivate'}}
179 template<typename T
, typename U
>
180 // expected-note@-1{{template parameter is declared here}}
181 concept C8
= sizeof(T
) > sizeof(U
);
183 template<typename
... T
>
184 constexpr bool B8
= C8
<T
...>;
185 // expected-error@-1{{pack expansion used as argument for non-pack parameter of concept}}
188 // Make sure we correctly check for containsUnexpandedParameterPack
193 template <typename Fn
, typename
... Args
>
194 using invoke
= typename
Fn::template invoke
<Args
...>;
196 template <typename C
, typename
... L
>
197 // The converted argument here will not containsUnexpandedParameterPack, but the
198 // as-written one will.
199 requires (C9
<invoke
<C
, L
>> &&...)