15d98ba60SSaar Raz // RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s 25d98ba60SSaar Raz 35d98ba60SSaar Raz template<typename T> concept C1 = true; // expected-note{{template is declared here}} 45d98ba60SSaar Raz static_assert(C1<int>); 55d98ba60SSaar Raz static_assert(C1); 65d98ba60SSaar Raz // expected-error@-1{{use of concept 'C1' requires template arguments}} 75d98ba60SSaar Raz 85d98ba60SSaar Raz template<typename T> concept C2 = sizeof(T) == 4; 95d98ba60SSaar Raz static_assert(C2<int>); 105d98ba60SSaar Raz static_assert(!C2<long long int>); 115d98ba60SSaar Raz static_assert(C2<char[4]>); 125d98ba60SSaar Raz static_assert(!C2<char[5]>); 135d98ba60SSaar Raz 145d98ba60SSaar Raz template<typename T> concept C3 = sizeof(*T{}) == 4; 155d98ba60SSaar Raz static_assert(C3<int*>); 165d98ba60SSaar Raz static_assert(!C3<long long int>); 175d98ba60SSaar Raz 185d98ba60SSaar Raz struct A { addA195d98ba60SSaar Raz static constexpr int add(int a, int b) { 205d98ba60SSaar Raz return a + b; 215d98ba60SSaar Raz } 225d98ba60SSaar Raz }; 235d98ba60SSaar Raz struct B { addB245d98ba60SSaar Raz static int add(int a, int b) { // expected-note{{declared here}} 255d98ba60SSaar Raz return a + b; 265d98ba60SSaar Raz } 275d98ba60SSaar Raz }; 285d98ba60SSaar Raz template<typename U> 295d98ba60SSaar Raz concept C4 = U::add(1, 2) == 3; 305d98ba60SSaar Raz // expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}} 315d98ba60SSaar Raz // expected-note@-2{{non-constexpr function 'add' cannot be used in a constant expression}} 325d98ba60SSaar Raz static_assert(C4<A>); 335d98ba60SSaar Raz static_assert(!C4<B>); // expected-note {{while checking the satisfaction of concept 'C4<B>' requested here}} 345d98ba60SSaar Raz 355d98ba60SSaar Raz template<typename T, typename U> 365d98ba60SSaar Raz constexpr bool is_same_v = false; 375d98ba60SSaar Raz 385d98ba60SSaar Raz template<typename T> 395d98ba60SSaar Raz constexpr bool is_same_v<T, T> = true; 405d98ba60SSaar Raz 415d98ba60SSaar Raz template<typename T, typename U> 425d98ba60SSaar Raz concept Same = is_same_v<T, U>; 435d98ba60SSaar Raz 445d98ba60SSaar Raz static_assert(Same<int, int>); 455d98ba60SSaar Raz static_assert(Same<int, decltype(1)>); 465d98ba60SSaar Raz static_assert(!Same<int, unsigned int>); 475d98ba60SSaar Raz static_assert(!Same<A, B>); 485d98ba60SSaar Raz static_assert(Same<A, A>); 495d98ba60SSaar Raz 505d98ba60SSaar Raz static_assert(Same<bool, decltype(C1<int>)>); 515d98ba60SSaar Raz static_assert(Same<bool, decltype(C2<int>)>); 525d98ba60SSaar Raz static_assert(Same<bool, decltype(C3<int*>)>); 535d98ba60SSaar Raz static_assert(Same<bool, decltype(C4<A>)>); 545d98ba60SSaar Raz 555d98ba60SSaar Raz template<typename T> concept C5 = T{}; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}} 565d98ba60SSaar Raz constexpr bool x = C5<int>; // expected-note {{while checking the satisfaction of concept 'C5<int>' requested here}} 575d98ba60SSaar Raz 585d98ba60SSaar Raz template<int x> 595d98ba60SSaar Raz concept IsEven = (x % 2) == 0; 605d98ba60SSaar Raz 615d98ba60SSaar Raz static_assert(IsEven<20>); 625d98ba60SSaar Raz static_assert(!IsEven<11>); 635d98ba60SSaar Raz 645d98ba60SSaar Raz template<template<typename T> typename P> 655d98ba60SSaar Raz concept IsTypePredicate = is_same_v<decltype(P<bool>::value), const bool> 665d98ba60SSaar Raz && is_same_v<decltype(P<int>::value), const bool> 675d98ba60SSaar Raz && is_same_v<decltype(P<long long>::value), const bool>; 685d98ba60SSaar Raz 695d98ba60SSaar Raz template<typename T> struct T1 {}; 705d98ba60SSaar Raz template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; }; 715d98ba60SSaar Raz 725d98ba60SSaar Raz static_assert(IsTypePredicate<T2>); 735d98ba60SSaar Raz static_assert(!IsTypePredicate<T1>); 745d98ba60SSaar Raz 75fdf80e86SSaar Raz template<typename T, typename U, typename... Ts> 76fdf80e86SSaar Raz concept OneOf = (Same<T, Ts> || ...); 77fdf80e86SSaar Raz 78df061c3eSSaar Raz static_assert(OneOf<int, long, int>); 79df061c3eSSaar Raz static_assert(!OneOf<long, int, char, char>); 80fdf80e86SSaar Raz 815d98ba60SSaar Raz namespace piecewise_substitution { 825d98ba60SSaar Raz template <typename T> 835d98ba60SSaar Raz concept True = true; 845d98ba60SSaar Raz 855d98ba60SSaar Raz template <typename T> 865d98ba60SSaar Raz concept A = True<T> || T::value; 875d98ba60SSaar Raz 885d98ba60SSaar Raz template <typename T> 895d98ba60SSaar Raz concept B = (True<T> || T::value); 905d98ba60SSaar Raz 915d98ba60SSaar Raz template <typename T> 925d98ba60SSaar Raz concept C = !True<T> && T::value || true; 935d98ba60SSaar Raz 945d98ba60SSaar Raz template <typename T> 955d98ba60SSaar Raz concept D = (!True<T> && T::value) || true; 965d98ba60SSaar Raz 975d98ba60SSaar Raz template <typename T> 985d98ba60SSaar Raz concept E = T::value || True<T>; 995d98ba60SSaar Raz 1005d98ba60SSaar Raz template <typename T> 1015d98ba60SSaar Raz concept F = (T::value || True<T>); 1025d98ba60SSaar Raz 1035d98ba60SSaar Raz template <typename T> 1045d98ba60SSaar Raz concept G = T::value && !True<T> || true; 1055d98ba60SSaar Raz 1065d98ba60SSaar Raz template <typename T> 1075d98ba60SSaar Raz concept H = (T::value && !True<T>) || true; 1085d98ba60SSaar Raz 1095d98ba60SSaar Raz template <typename T> 1105d98ba60SSaar Raz concept I = T::value; 1115d98ba60SSaar Raz 1125d98ba60SSaar Raz static_assert(A<int>); 1135d98ba60SSaar Raz static_assert(B<int>); 1145d98ba60SSaar Raz static_assert(C<int>); 1155d98ba60SSaar Raz static_assert(D<int>); 1165d98ba60SSaar Raz static_assert(E<int>); 1175d98ba60SSaar Raz static_assert(F<int>); 1185d98ba60SSaar Raz static_assert(G<int>); 1195d98ba60SSaar Raz static_assert(H<int>); 1205d98ba60SSaar Raz static_assert(!I<int>); 1215d98ba60SSaar Raz } 1225d98ba60SSaar Raz 1235d98ba60SSaar Raz // Short ciruiting 1245d98ba60SSaar Raz 1255d98ba60SSaar Raz template<typename T> struct T3 { using type = typename T::type; }; 1265d98ba60SSaar Raz // expected-error@-1{{type 'char' cannot be used prior to '::' because it has no members}} 1275d98ba60SSaar Raz // expected-error@-2{{type 'short' cannot be used prior to '::' because it has no members}} 1285d98ba60SSaar Raz 1295d98ba60SSaar Raz template<typename T> 1305d98ba60SSaar Raz concept C6 = sizeof(T) == 1 && sizeof(typename T3<T>::type) == 1; 1315d98ba60SSaar Raz // expected-note@-1{{while substituting template arguments into constraint expression here}} 1325d98ba60SSaar Raz // expected-note@-2{{in instantiation of template class 'T3<char>' requested here}} 1335d98ba60SSaar Raz 1345d98ba60SSaar Raz template<typename T> 1355d98ba60SSaar Raz concept C7 = sizeof(T) == 1 || sizeof( 1365d98ba60SSaar Raz // expected-note@-1{{while substituting template arguments into constraint expression here}} 1375d98ba60SSaar Raz typename 1385d98ba60SSaar Raz T3<T> 1395d98ba60SSaar Raz // expected-note@-1{{in instantiation of template class 'T3<short>' requested here}} 1405d98ba60SSaar Raz ::type) == 1; 1415d98ba60SSaar Raz 1425d98ba60SSaar Raz static_assert(!C6<short>); 1435d98ba60SSaar Raz static_assert(!C6<char>); // expected-note{{while checking the satisfaction of concept 'C6<char>' requested here}} 1445d98ba60SSaar Raz static_assert(C7<char>); 1455d98ba60SSaar Raz static_assert(!C7<short>); // expected-note{{while checking the satisfaction of concept 'C7<short>' requested here}} 1465d98ba60SSaar Raz 1475d98ba60SSaar Raz // Make sure argument list is converted when instantiating a CSE. 1485d98ba60SSaar Raz 1495d98ba60SSaar Raz template<typename T, typename U = int> 1505d98ba60SSaar Raz concept SameSize = sizeof(T) == sizeof(U); 1515d98ba60SSaar Raz 1525d98ba60SSaar Raz template<typename T> 1535d98ba60SSaar Raz struct X { static constexpr bool a = SameSize<T>; }; 1545d98ba60SSaar Raz 1555d98ba60SSaar Raz static_assert(X<unsigned>::a); 156fdf80e86SSaar Raz 157fdf80e86SSaar Raz // static_assert concept diagnostics 158fdf80e86SSaar Raz template<typename T> 159fdf80e86SSaar Raz concept Large = sizeof(T) > 100; 160fdf80e86SSaar Raz // expected-note@-1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}} 161fdf80e86SSaar Raz 162fdf80e86SSaar Raz struct small { }; 163fdf80e86SSaar Raz static_assert(Large<small>); 164*76476efdSMuhammad Usman Shahid // expected-error@-1 {{static assertion failed}} 165fdf80e86SSaar Raz // expected-note@-2 {{because 'small' does not satisfy 'Large'}} 166fdf80e86SSaar Raz static_assert(Large<small>, "small isn't large"); 167*76476efdSMuhammad Usman Shahid // expected-error@-1 {{static assertion failed: small isn't large}} 168fdf80e86SSaar Raz // expected-note@-2 {{because 'small' does not satisfy 'Large'}} 169fdf80e86SSaar Raz 170fdf80e86SSaar Raz // Make sure access-checking can fail a concept specialization 171fdf80e86SSaar Raz 172fdf80e86SSaar Raz class T4 { static constexpr bool f = true; }; 173fdf80e86SSaar Raz template<typename T> concept AccessPrivate = T{}.f; 174fdf80e86SSaar Raz // expected-note@-1{{because substituted constraint expression is ill-formed: 'f' is a private member of 'T4'}} 175fdf80e86SSaar Raz static_assert(AccessPrivate<T4>); 176*76476efdSMuhammad Usman Shahid // expected-error@-1{{static assertion failed}} 177fdf80e86SSaar Raz // expected-note@-2{{because 'T4' does not satisfy 'AccessPrivate'}} 178df061c3eSSaar Raz 179df061c3eSSaar Raz template<typename T, typename U> 180df061c3eSSaar Raz // expected-note@-1{{template parameter is declared here}} 181df061c3eSSaar Raz concept C8 = sizeof(T) > sizeof(U); 182df061c3eSSaar Raz 183df061c3eSSaar Raz template<typename... T> 184df061c3eSSaar Raz constexpr bool B8 = C8<T...>; 185df061c3eSSaar Raz // expected-error@-1{{pack expansion used as argument for non-pack parameter of concept}} 186c83d9bedSSaar Raz 187c83d9bedSSaar Raz 188c83d9bedSSaar Raz // Make sure we correctly check for containsUnexpandedParameterPack 189c83d9bedSSaar Raz 190c83d9bedSSaar Raz template<typename T> 191c83d9bedSSaar Raz concept C9 = true; 192c83d9bedSSaar Raz 193c83d9bedSSaar Raz template <typename Fn, typename... Args> 194c83d9bedSSaar Raz using invoke = typename Fn::template invoke<Args...>; 195c83d9bedSSaar Raz 196c83d9bedSSaar Raz template <typename C, typename... L> 197c83d9bedSSaar Raz // The converted argument here will not containsUnexpandedParameterPack, but the 198c83d9bedSSaar Raz // as-written one will. 199c83d9bedSSaar Raz requires (C9<invoke<C, L>> &&...) 200c83d9bedSSaar Raz struct S { }; 201