1 // RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s 2 3 template<typename T> concept C1 = true; // expected-note{{template is declared here}} 4 static_assert(C1<int>); 5 static_assert(C1); 6 // expected-error@-1{{use of concept 'C1' requires template arguments}} 7 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]>); 13 14 template<typename T> concept C3 = sizeof(*T{}) == 4; 15 static_assert(C3<int*>); 16 static_assert(!C3<long long int>); 17 18 struct A { addA19 static constexpr int add(int a, int b) { 20 return a + b; 21 } 22 }; 23 struct B { addB24 static int add(int a, int b) { // expected-note{{declared here}} 25 return a + b; 26 } 27 }; 28 template<typename U> 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}} 32 static_assert(C4<A>); 33 static_assert(!C4<B>); // expected-note {{while checking the satisfaction of concept 'C4<B>' requested here}} 34 35 template<typename T, typename U> 36 constexpr bool is_same_v = false; 37 38 template<typename T> 39 constexpr bool is_same_v<T, T> = true; 40 41 template<typename T, typename U> 42 concept Same = is_same_v<T, U>; 43 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>); 49 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>)>); 54 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}} 57 58 template<int x> 59 concept IsEven = (x % 2) == 0; 60 61 static_assert(IsEven<20>); 62 static_assert(!IsEven<11>); 63 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>; 68 69 template<typename T> struct T1 {}; 70 template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; }; 71 72 static_assert(IsTypePredicate<T2>); 73 static_assert(!IsTypePredicate<T1>); 74 75 template<typename T, typename U, typename... Ts> 76 concept OneOf = (Same<T, Ts> || ...); 77 78 static_assert(OneOf<int, long, int>); 79 static_assert(!OneOf<long, int, char, char>); 80 81 namespace piecewise_substitution { 82 template <typename T> 83 concept True = true; 84 85 template <typename T> 86 concept A = True<T> || T::value; 87 88 template <typename T> 89 concept B = (True<T> || T::value); 90 91 template <typename T> 92 concept C = !True<T> && T::value || true; 93 94 template <typename T> 95 concept D = (!True<T> && T::value) || true; 96 97 template <typename T> 98 concept E = T::value || True<T>; 99 100 template <typename T> 101 concept F = (T::value || True<T>); 102 103 template <typename T> 104 concept G = T::value && !True<T> || true; 105 106 template <typename T> 107 concept H = (T::value && !True<T>) || true; 108 109 template <typename T> 110 concept I = T::value; 111 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>); 121 } 122 123 // Short ciruiting 124 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}} 128 129 template<typename T> 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}} 133 134 template<typename T> 135 concept C7 = sizeof(T) == 1 || sizeof( 136 // expected-note@-1{{while substituting template arguments into constraint expression here}} 137 typename 138 T3<T> 139 // expected-note@-1{{in instantiation of template class 'T3<short>' requested here}} 140 ::type) == 1; 141 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}} 146 147 // Make sure argument list is converted when instantiating a CSE. 148 149 template<typename T, typename U = int> 150 concept SameSize = sizeof(T) == sizeof(U); 151 152 template<typename T> 153 struct X { static constexpr bool a = SameSize<T>; }; 154 155 static_assert(X<unsigned>::a); 156 157 // static_assert concept diagnostics 158 template<typename T> 159 concept Large = sizeof(T) > 100; 160 // expected-note@-1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}} 161 162 struct small { }; 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'}} 169 170 // Make sure access-checking can fail a concept specialization 171 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'}} 178 179 template<typename T, typename U> 180 // expected-note@-1{{template parameter is declared here}} 181 concept C8 = sizeof(T) > sizeof(U); 182 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}} 186 187 188 // Make sure we correctly check for containsUnexpandedParameterPack 189 190 template<typename T> 191 concept C9 = true; 192 193 template <typename Fn, typename... Args> 194 using invoke = typename Fn::template invoke<Args...>; 195 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>> &&...) 200 struct S { }; 201