1421c098bSAlexander Shaposhnikov // RUN: %clang_cc1 -std=c++20 -verify %s 2421c098bSAlexander Shaposhnikov 3421c098bSAlexander Shaposhnikov static constexpr int PRIMARY = 0; 4421c098bSAlexander Shaposhnikov static constexpr int SPECIALIZATION_CONCEPT = 1; 5421c098bSAlexander Shaposhnikov static constexpr int SPECIALIZATION_REQUIRES = 2; 6421c098bSAlexander Shaposhnikov 7421c098bSAlexander Shaposhnikov template <class T> 8421c098bSAlexander Shaposhnikov concept Concept = (sizeof(T) >= 2 * sizeof(int)); 9421c098bSAlexander Shaposhnikov 10421c098bSAlexander Shaposhnikov struct XY { 11421c098bSAlexander Shaposhnikov int x; 12421c098bSAlexander Shaposhnikov int y; 13421c098bSAlexander Shaposhnikov }; 14421c098bSAlexander Shaposhnikov 15421c098bSAlexander Shaposhnikov namespace members { 16421c098bSAlexander Shaposhnikov 17421c098bSAlexander Shaposhnikov template <class T, class U> struct S { 18421c098bSAlexander Shaposhnikov static constexpr int primary(); 19421c098bSAlexander Shaposhnikov }; 20421c098bSAlexander Shaposhnikov 21421c098bSAlexander Shaposhnikov template <class T, class U> constexpr int S<T, U>::primary() { 22421c098bSAlexander Shaposhnikov return PRIMARY; 23421c098bSAlexander Shaposhnikov }; 24421c098bSAlexander Shaposhnikov 25421c098bSAlexander Shaposhnikov template <Concept C, class U> struct S<C, U> { 26421c098bSAlexander Shaposhnikov static constexpr int specialization(); 27421c098bSAlexander Shaposhnikov }; 28421c098bSAlexander Shaposhnikov 29421c098bSAlexander Shaposhnikov template <class T, class U> 30421c098bSAlexander Shaposhnikov requires(sizeof(T) == sizeof(int)) 31421c098bSAlexander Shaposhnikov struct S<T, U> { 32421c098bSAlexander Shaposhnikov static constexpr int specialization(); 33421c098bSAlexander Shaposhnikov }; 34421c098bSAlexander Shaposhnikov 35421c098bSAlexander Shaposhnikov template <Concept C, class U> constexpr int S<C, U>::specialization() { 36421c098bSAlexander Shaposhnikov return SPECIALIZATION_CONCEPT; 37421c098bSAlexander Shaposhnikov } 38421c098bSAlexander Shaposhnikov 39421c098bSAlexander Shaposhnikov template <class T, class U> 40421c098bSAlexander Shaposhnikov requires(sizeof(T) == sizeof(int)) 41421c098bSAlexander Shaposhnikov constexpr int S<T, U>::specialization() { 42421c098bSAlexander Shaposhnikov return SPECIALIZATION_REQUIRES; 43421c098bSAlexander Shaposhnikov } 44421c098bSAlexander Shaposhnikov 45421c098bSAlexander Shaposhnikov static_assert(S<char, double>::primary() == PRIMARY); 46421c098bSAlexander Shaposhnikov static_assert(S<XY, double>::specialization() == SPECIALIZATION_CONCEPT); 47421c098bSAlexander Shaposhnikov static_assert(S<int, double>::specialization() == SPECIALIZATION_REQUIRES); 48421c098bSAlexander Shaposhnikov 49421c098bSAlexander Shaposhnikov } // namespace members 50421c098bSAlexander Shaposhnikov 51421c098bSAlexander Shaposhnikov namespace enumerations { 52421c098bSAlexander Shaposhnikov 53421c098bSAlexander Shaposhnikov template <class T, class U> struct S { 54421c098bSAlexander Shaposhnikov enum class E : int; 55421c098bSAlexander Shaposhnikov }; 56421c098bSAlexander Shaposhnikov 57421c098bSAlexander Shaposhnikov template <class T, class U> enum class S<T, U>::E { Value = PRIMARY }; 58421c098bSAlexander Shaposhnikov 59421c098bSAlexander Shaposhnikov template <Concept C, class U> struct S<C, U> { 60421c098bSAlexander Shaposhnikov enum class E : int; 61421c098bSAlexander Shaposhnikov }; 62421c098bSAlexander Shaposhnikov 63421c098bSAlexander Shaposhnikov template <Concept C, class U> 64421c098bSAlexander Shaposhnikov enum class S<C, U>::E { 65421c098bSAlexander Shaposhnikov Value = SPECIALIZATION_CONCEPT 66421c098bSAlexander Shaposhnikov }; 67421c098bSAlexander Shaposhnikov 68421c098bSAlexander Shaposhnikov template <class T, class U> 69421c098bSAlexander Shaposhnikov requires(sizeof(T) == sizeof(int)) 70421c098bSAlexander Shaposhnikov struct S<T, U> { 71421c098bSAlexander Shaposhnikov enum class E : int; 72421c098bSAlexander Shaposhnikov }; 73421c098bSAlexander Shaposhnikov 74421c098bSAlexander Shaposhnikov template <class T, class U> 75421c098bSAlexander Shaposhnikov requires(sizeof(T) == sizeof(int)) 76421c098bSAlexander Shaposhnikov enum class S<T, U>::E { 77421c098bSAlexander Shaposhnikov Value = SPECIALIZATION_REQUIRES 78421c098bSAlexander Shaposhnikov }; 79421c098bSAlexander Shaposhnikov 80421c098bSAlexander Shaposhnikov static_assert(static_cast<int>(S<char, double>::E::Value) == PRIMARY); 81421c098bSAlexander Shaposhnikov static_assert(static_cast<int>(S<XY, double>::E::Value) == 82421c098bSAlexander Shaposhnikov SPECIALIZATION_CONCEPT); 83421c098bSAlexander Shaposhnikov static_assert(static_cast<int>(S<int, double>::E::Value) == 84421c098bSAlexander Shaposhnikov SPECIALIZATION_REQUIRES); 85421c098bSAlexander Shaposhnikov 86421c098bSAlexander Shaposhnikov } // namespace enumerations 87421c098bSAlexander Shaposhnikov 88421c098bSAlexander Shaposhnikov namespace multiple_template_parameter_lists { 89421c098bSAlexander Shaposhnikov 90421c098bSAlexander Shaposhnikov template <class Outer> 91421c098bSAlexander Shaposhnikov struct S { 92421c098bSAlexander Shaposhnikov template <class Inner> 93421c098bSAlexander Shaposhnikov static constexpr int primary(Inner); 94421c098bSAlexander Shaposhnikov }; 95421c098bSAlexander Shaposhnikov 96421c098bSAlexander Shaposhnikov template <class Outer> 97421c098bSAlexander Shaposhnikov template <class Inner> 98421c098bSAlexander Shaposhnikov constexpr int S<Outer>::primary(Inner) { 99421c098bSAlexander Shaposhnikov return PRIMARY; 100421c098bSAlexander Shaposhnikov }; 101421c098bSAlexander Shaposhnikov 102421c098bSAlexander Shaposhnikov template <Concept Outer> 103421c098bSAlexander Shaposhnikov struct S<Outer> { 104421c098bSAlexander Shaposhnikov template <class Inner> 105421c098bSAlexander Shaposhnikov static constexpr int specialization(Inner); 106421c098bSAlexander Shaposhnikov }; 107421c098bSAlexander Shaposhnikov 108421c098bSAlexander Shaposhnikov template <Concept Outer> 109421c098bSAlexander Shaposhnikov template <class Inner> 110421c098bSAlexander Shaposhnikov constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_CONCEPT; } 111421c098bSAlexander Shaposhnikov 112421c098bSAlexander Shaposhnikov template <class Outer> 113421c098bSAlexander Shaposhnikov requires(sizeof(Outer) == sizeof(int)) 114421c098bSAlexander Shaposhnikov struct S<Outer> { 115421c098bSAlexander Shaposhnikov template <class Inner> 116421c098bSAlexander Shaposhnikov static constexpr int specialization(Inner); 117421c098bSAlexander Shaposhnikov }; 118421c098bSAlexander Shaposhnikov 119421c098bSAlexander Shaposhnikov template <class Outer> 120421c098bSAlexander Shaposhnikov requires(sizeof(Outer) == sizeof(int)) 121421c098bSAlexander Shaposhnikov template <class Inner> 122421c098bSAlexander Shaposhnikov constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_REQUIRES; } 123421c098bSAlexander Shaposhnikov 124421c098bSAlexander Shaposhnikov static_assert(S<char>::primary("str") == PRIMARY); 125421c098bSAlexander Shaposhnikov static_assert(S<XY>::specialization("str") == SPECIALIZATION_CONCEPT); 126421c098bSAlexander Shaposhnikov static_assert(S<int>::specialization("str") == SPECIALIZATION_REQUIRES); 127421c098bSAlexander Shaposhnikov 128421c098bSAlexander Shaposhnikov } // namespace multiple_template_parameter_lists 1296db007a0SAlexander Shaposhnikov 1306db007a0SAlexander Shaposhnikov static constexpr int CONSTRAINED_METHOD_1 = 1; 1316db007a0SAlexander Shaposhnikov static constexpr int CONSTRAINED_METHOD_2 = 2; 1326db007a0SAlexander Shaposhnikov 1336db007a0SAlexander Shaposhnikov namespace constrained_members { 1346db007a0SAlexander Shaposhnikov 1356db007a0SAlexander Shaposhnikov template <int> 1366db007a0SAlexander Shaposhnikov struct S { 1376db007a0SAlexander Shaposhnikov template <Concept C> 1386db007a0SAlexander Shaposhnikov static constexpr int constrained_method(); 1396db007a0SAlexander Shaposhnikov }; 1406db007a0SAlexander Shaposhnikov 1416db007a0SAlexander Shaposhnikov template <> 1426db007a0SAlexander Shaposhnikov template <Concept C> 1436db007a0SAlexander Shaposhnikov constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; } 1446db007a0SAlexander Shaposhnikov 1456db007a0SAlexander Shaposhnikov template <> 1466db007a0SAlexander Shaposhnikov template <Concept C> 1476db007a0SAlexander Shaposhnikov constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; } 1486db007a0SAlexander Shaposhnikov 1496db007a0SAlexander Shaposhnikov static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1); 1506db007a0SAlexander Shaposhnikov static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2); 1516db007a0SAlexander Shaposhnikov 1526db007a0SAlexander Shaposhnikov 1536db007a0SAlexander Shaposhnikov template <class T1, class T2> 1546db007a0SAlexander Shaposhnikov concept ConceptT1T2 = true; 1556db007a0SAlexander Shaposhnikov 1566db007a0SAlexander Shaposhnikov template<typename T3> 1576db007a0SAlexander Shaposhnikov struct S12 { 1586db007a0SAlexander Shaposhnikov template<ConceptT1T2<T3> T4> 1596db007a0SAlexander Shaposhnikov static constexpr int constrained_method(); 1606db007a0SAlexander Shaposhnikov }; 1616db007a0SAlexander Shaposhnikov 1626db007a0SAlexander Shaposhnikov template<> 1636db007a0SAlexander Shaposhnikov template<ConceptT1T2<int> T5> 1646db007a0SAlexander Shaposhnikov constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; } 1656db007a0SAlexander Shaposhnikov 1666db007a0SAlexander Shaposhnikov template<> 1676db007a0SAlexander Shaposhnikov template<ConceptT1T2<double> T5> 1686db007a0SAlexander Shaposhnikov constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; } 1696db007a0SAlexander Shaposhnikov 1706db007a0SAlexander Shaposhnikov static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1); 1716db007a0SAlexander Shaposhnikov static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2); 1726db007a0SAlexander Shaposhnikov 1736db007a0SAlexander Shaposhnikov } // namespace constrained members 1746db007a0SAlexander Shaposhnikov 1756db007a0SAlexander Shaposhnikov namespace constrained_members_of_nested_types { 1766db007a0SAlexander Shaposhnikov 1776db007a0SAlexander Shaposhnikov template <int> 1786db007a0SAlexander Shaposhnikov struct S { 1796db007a0SAlexander Shaposhnikov struct Inner0 { 1806db007a0SAlexander Shaposhnikov struct Inner1 { 1816db007a0SAlexander Shaposhnikov template <Concept C> 1826db007a0SAlexander Shaposhnikov static constexpr int constrained_method(); 1836db007a0SAlexander Shaposhnikov }; 1846db007a0SAlexander Shaposhnikov }; 1856db007a0SAlexander Shaposhnikov }; 1866db007a0SAlexander Shaposhnikov 1876db007a0SAlexander Shaposhnikov template <> 1886db007a0SAlexander Shaposhnikov template <Concept C> 1896db007a0SAlexander Shaposhnikov constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } 1906db007a0SAlexander Shaposhnikov 1916db007a0SAlexander Shaposhnikov template <> 1926db007a0SAlexander Shaposhnikov template <Concept C> 1936db007a0SAlexander Shaposhnikov constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } 1946db007a0SAlexander Shaposhnikov 1956db007a0SAlexander Shaposhnikov static_assert(S<1>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1); 1966db007a0SAlexander Shaposhnikov static_assert(S<2>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2); 1976db007a0SAlexander Shaposhnikov 1986db007a0SAlexander Shaposhnikov 1996db007a0SAlexander Shaposhnikov template <class T1, class T2> 2006db007a0SAlexander Shaposhnikov concept ConceptT1T2 = true; 2016db007a0SAlexander Shaposhnikov 2026db007a0SAlexander Shaposhnikov template<typename T3> 2036db007a0SAlexander Shaposhnikov struct S12 { 2046db007a0SAlexander Shaposhnikov struct Inner0 { 2056db007a0SAlexander Shaposhnikov struct Inner1 { 2066db007a0SAlexander Shaposhnikov template<ConceptT1T2<T3> T4> 2076db007a0SAlexander Shaposhnikov static constexpr int constrained_method(); 2086db007a0SAlexander Shaposhnikov }; 2096db007a0SAlexander Shaposhnikov }; 2106db007a0SAlexander Shaposhnikov }; 2116db007a0SAlexander Shaposhnikov 2126db007a0SAlexander Shaposhnikov template<> 2136db007a0SAlexander Shaposhnikov template<ConceptT1T2<int> T5> 2146db007a0SAlexander Shaposhnikov constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } 2156db007a0SAlexander Shaposhnikov 2166db007a0SAlexander Shaposhnikov template<> 2176db007a0SAlexander Shaposhnikov template<ConceptT1T2<double> T5> 2186db007a0SAlexander Shaposhnikov constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } 2196db007a0SAlexander Shaposhnikov 2206db007a0SAlexander Shaposhnikov static_assert(S12<int>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1); 2216db007a0SAlexander Shaposhnikov static_assert(S12<double>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2); 2226db007a0SAlexander Shaposhnikov 2236db007a0SAlexander Shaposhnikov } // namespace constrained_members_of_nested_types 2246db007a0SAlexander Shaposhnikov 2256db007a0SAlexander Shaposhnikov namespace constrained_member_sfinae { 2266db007a0SAlexander Shaposhnikov 2276db007a0SAlexander Shaposhnikov template<int N> struct S { 2286db007a0SAlexander Shaposhnikov template<class T> 22984a3aadfSAaron Ballman static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) { // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 23084a3aadfSAaron Ballman expected-note {{value 4294967296 is outside the range of representable values of type 'int'}} \ 23184a3aadfSAaron Ballman expected-note {{while calculating associated constraint of template 'constrained_method' here}} 2326db007a0SAlexander Shaposhnikov return CONSTRAINED_METHOD_1; 2336db007a0SAlexander Shaposhnikov } 2346db007a0SAlexander Shaposhnikov 2356db007a0SAlexander Shaposhnikov template<class T> 2366db007a0SAlexander Shaposhnikov static constexpr int constrained_method() requires (sizeof(int[N]) == 16); 2376db007a0SAlexander Shaposhnikov }; 2386db007a0SAlexander Shaposhnikov 2396db007a0SAlexander Shaposhnikov template<> 2406db007a0SAlexander Shaposhnikov template<typename T> 2416db007a0SAlexander Shaposhnikov constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) { 2426db007a0SAlexander Shaposhnikov return CONSTRAINED_METHOD_2; 2436db007a0SAlexander Shaposhnikov } 2446db007a0SAlexander Shaposhnikov 2456db007a0SAlexander Shaposhnikov // Verify that there is no amiguity in this case. 2466db007a0SAlexander Shaposhnikov static_assert(S<4>::constrained_method<double>() == CONSTRAINED_METHOD_2); 2476db007a0SAlexander Shaposhnikov 2486db007a0SAlexander Shaposhnikov } // namespace constrained_member_sfinae 2496db007a0SAlexander Shaposhnikov 2506db007a0SAlexander Shaposhnikov namespace requires_expression_references_members { 2516db007a0SAlexander Shaposhnikov 2526db007a0SAlexander Shaposhnikov void accept1(int x); 2536db007a0SAlexander Shaposhnikov void accept2(XY xy); 2546db007a0SAlexander Shaposhnikov 2556db007a0SAlexander Shaposhnikov template <class T> struct S { 2566db007a0SAlexander Shaposhnikov T Field = T(); 2576db007a0SAlexander Shaposhnikov 2586db007a0SAlexander Shaposhnikov constexpr int constrained_method() 2596db007a0SAlexander Shaposhnikov requires requires { accept1(Field); }; 2606db007a0SAlexander Shaposhnikov 2616db007a0SAlexander Shaposhnikov constexpr int constrained_method() 2626db007a0SAlexander Shaposhnikov requires requires { accept2(Field); }; 2636db007a0SAlexander Shaposhnikov }; 2646db007a0SAlexander Shaposhnikov 2656db007a0SAlexander Shaposhnikov template <class T> 2666db007a0SAlexander Shaposhnikov constexpr int S<T>::constrained_method() 2676db007a0SAlexander Shaposhnikov requires requires { accept1(Field); } { 2686db007a0SAlexander Shaposhnikov return CONSTRAINED_METHOD_1; 2696db007a0SAlexander Shaposhnikov } 2706db007a0SAlexander Shaposhnikov 2716db007a0SAlexander Shaposhnikov template <class T> 2726db007a0SAlexander Shaposhnikov constexpr int S<T>::constrained_method() 2736db007a0SAlexander Shaposhnikov requires requires { accept2(Field); } { 2746db007a0SAlexander Shaposhnikov return CONSTRAINED_METHOD_2; 2756db007a0SAlexander Shaposhnikov } 2766db007a0SAlexander Shaposhnikov 2776db007a0SAlexander Shaposhnikov static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1); 2786db007a0SAlexander Shaposhnikov static_assert(S<XY>().constrained_method() == CONSTRAINED_METHOD_2); 2796db007a0SAlexander Shaposhnikov 2806db007a0SAlexander Shaposhnikov } // namespace requires_expression_references_members 2816db007a0SAlexander Shaposhnikov 2826db007a0SAlexander Shaposhnikov namespace GH60231 { 2836db007a0SAlexander Shaposhnikov 2846db007a0SAlexander Shaposhnikov template<typename T0> concept C = true; 2856db007a0SAlexander Shaposhnikov 2866db007a0SAlexander Shaposhnikov template <typename T1> 2876db007a0SAlexander Shaposhnikov struct S { 2886db007a0SAlexander Shaposhnikov template <typename F1> requires C<S<T1>> 2896db007a0SAlexander Shaposhnikov void foo1(F1 f); 2906db007a0SAlexander Shaposhnikov 2916db007a0SAlexander Shaposhnikov template <typename F2> 2926db007a0SAlexander Shaposhnikov void foo2(F2 f) requires C<S<T1>>; 2936db007a0SAlexander Shaposhnikov 2946db007a0SAlexander Shaposhnikov template <typename F3> requires C<F3> 2956db007a0SAlexander Shaposhnikov void foo3(F3 f); 2966db007a0SAlexander Shaposhnikov }; 2976db007a0SAlexander Shaposhnikov 2986db007a0SAlexander Shaposhnikov template <typename T2> 2996db007a0SAlexander Shaposhnikov template <typename F4> requires C<S<T2>> 3006db007a0SAlexander Shaposhnikov void S<T2>::foo1(F4 f) {} 3016db007a0SAlexander Shaposhnikov 3026db007a0SAlexander Shaposhnikov template <typename T3> 3036db007a0SAlexander Shaposhnikov template <typename F5> 3046db007a0SAlexander Shaposhnikov void S<T3>::foo2(F5 f) requires C<S<T3>> {} 3056db007a0SAlexander Shaposhnikov 3066db007a0SAlexander Shaposhnikov template <typename T4> 3076db007a0SAlexander Shaposhnikov template <typename F6> requires C<F6> 3086db007a0SAlexander Shaposhnikov void S<T4>::foo3(F6 f) {} 3096db007a0SAlexander Shaposhnikov 3106db007a0SAlexander Shaposhnikov } // namespace GH60231 3116db007a0SAlexander Shaposhnikov 3126db007a0SAlexander Shaposhnikov namespace GH62003 { 3136db007a0SAlexander Shaposhnikov 3146db007a0SAlexander Shaposhnikov template <typename T0> concept Concept = true; 3156db007a0SAlexander Shaposhnikov 3166db007a0SAlexander Shaposhnikov template <class T1> 3176db007a0SAlexander Shaposhnikov struct S1 { 3186db007a0SAlexander Shaposhnikov template <Concept C1> 3196db007a0SAlexander Shaposhnikov static constexpr int foo(); 3206db007a0SAlexander Shaposhnikov }; 3216db007a0SAlexander Shaposhnikov template <class T2> 3226db007a0SAlexander Shaposhnikov template <Concept C2> 3236db007a0SAlexander Shaposhnikov constexpr int S1<T2>::foo() { return 1; } 3246db007a0SAlexander Shaposhnikov 3256db007a0SAlexander Shaposhnikov template <Concept C3> 3266db007a0SAlexander Shaposhnikov struct S2 { 3276db007a0SAlexander Shaposhnikov template <class T3> 3286db007a0SAlexander Shaposhnikov static constexpr int foo(); 3296db007a0SAlexander Shaposhnikov }; 3306db007a0SAlexander Shaposhnikov template <Concept C4> 3316db007a0SAlexander Shaposhnikov template <class T4> 3326db007a0SAlexander Shaposhnikov constexpr int S2<C4>::foo() { return 2; } 3336db007a0SAlexander Shaposhnikov 3346db007a0SAlexander Shaposhnikov template <Concept C5> 3356db007a0SAlexander Shaposhnikov struct S3 { 3366db007a0SAlexander Shaposhnikov template <Concept C6> 3376db007a0SAlexander Shaposhnikov static constexpr int foo(); 3386db007a0SAlexander Shaposhnikov }; 3396db007a0SAlexander Shaposhnikov template <Concept C7> 3406db007a0SAlexander Shaposhnikov template <Concept C8> 3416db007a0SAlexander Shaposhnikov constexpr int S3<C7>::foo() { return 3; } 3426db007a0SAlexander Shaposhnikov 3436db007a0SAlexander Shaposhnikov static_assert(S1<int>::foo<int>() == 1); 3446db007a0SAlexander Shaposhnikov static_assert(S2<int>::foo<int>() == 2); 3456db007a0SAlexander Shaposhnikov static_assert(S3<int>::foo<int>() == 3); 3466db007a0SAlexander Shaposhnikov 3476db007a0SAlexander Shaposhnikov } // namespace GH62003 3486db007a0SAlexander Shaposhnikov 3496db007a0SAlexander Shaposhnikov namespace MultilevelTemplateWithPartialSpecialization { 3506db007a0SAlexander Shaposhnikov template <typename> 3516db007a0SAlexander Shaposhnikov concept Concept = true; 3526db007a0SAlexander Shaposhnikov 3536db007a0SAlexander Shaposhnikov namespace two_level { 3546db007a0SAlexander Shaposhnikov template <typename T1, int> 3556db007a0SAlexander Shaposhnikov struct W0 { 3566db007a0SAlexander Shaposhnikov template <typename T2> 3576db007a0SAlexander Shaposhnikov requires (Concept<T2>) 3586db007a0SAlexander Shaposhnikov void f(const T2 &); 3596db007a0SAlexander Shaposhnikov }; 3606db007a0SAlexander Shaposhnikov 3616db007a0SAlexander Shaposhnikov template <typename T3> 3626db007a0SAlexander Shaposhnikov struct W0<T3, 0> { 3636db007a0SAlexander Shaposhnikov template <typename T4> 3646db007a0SAlexander Shaposhnikov requires (Concept<T4>) 3656db007a0SAlexander Shaposhnikov void f(const T4 &); 3666db007a0SAlexander Shaposhnikov }; 3676db007a0SAlexander Shaposhnikov 3686db007a0SAlexander Shaposhnikov template <typename T3> 3696db007a0SAlexander Shaposhnikov template <typename T4> 3706db007a0SAlexander Shaposhnikov requires (Concept<T4>) 3716db007a0SAlexander Shaposhnikov inline void W0<T3, 0>::f(const T4 &) {} 3726db007a0SAlexander Shaposhnikov } // namespace two_level 3736db007a0SAlexander Shaposhnikov 3746db007a0SAlexander Shaposhnikov namespace three_level { 3756db007a0SAlexander Shaposhnikov template <typename T1, int> 3766db007a0SAlexander Shaposhnikov struct W0 { 3776db007a0SAlexander Shaposhnikov template <typename T2> 3786db007a0SAlexander Shaposhnikov struct W1 { 3796db007a0SAlexander Shaposhnikov template <typename T3> 3806db007a0SAlexander Shaposhnikov requires (Concept<T3>) 3816db007a0SAlexander Shaposhnikov void f(const T3 &); 3826db007a0SAlexander Shaposhnikov }; 3836db007a0SAlexander Shaposhnikov }; 3846db007a0SAlexander Shaposhnikov 3856db007a0SAlexander Shaposhnikov template <typename T4> 3866db007a0SAlexander Shaposhnikov struct W0<T4, 0> { 3876db007a0SAlexander Shaposhnikov template <typename T5> 3886db007a0SAlexander Shaposhnikov struct W1 { 3896db007a0SAlexander Shaposhnikov template <typename T6> 3906db007a0SAlexander Shaposhnikov requires (Concept<T6>) 3916db007a0SAlexander Shaposhnikov void f(const T6 &); 3926db007a0SAlexander Shaposhnikov }; 3936db007a0SAlexander Shaposhnikov }; 3946db007a0SAlexander Shaposhnikov 3956db007a0SAlexander Shaposhnikov template <typename T7> 3966db007a0SAlexander Shaposhnikov template <typename T8> 3976db007a0SAlexander Shaposhnikov template <typename T9> 3986db007a0SAlexander Shaposhnikov requires (Concept<T9>) 3996db007a0SAlexander Shaposhnikov inline void W0<T7, 0>::W1<T8>::f(const T9 &) {} 4006db007a0SAlexander Shaposhnikov } // namespace three_level 4016db007a0SAlexander Shaposhnikov 4026db007a0SAlexander Shaposhnikov } // namespace MultilevelTemplateWithPartialSpecialization 403fbd8f898SErich Keane 404fbd8f898SErich Keane namespace PR62697 { 405fbd8f898SErich Keane template<typename> 406fbd8f898SErich Keane concept c = true; 407fbd8f898SErich Keane 408fbd8f898SErich Keane template<typename T> 409fbd8f898SErich Keane struct s { 410fbd8f898SErich Keane void f() requires c<void(T)>; 411fbd8f898SErich Keane }; 412fbd8f898SErich Keane 413fbd8f898SErich Keane template<typename T> 414fbd8f898SErich Keane void s<T>::f() requires c<void(T)> { } 415fbd8f898SErich Keane } 4163a9683fcSRichard Smith 4173a9683fcSRichard Smith namespace GH62272 { 4183a9683fcSRichard Smith template<typename T> concept A = true; 4193a9683fcSRichard Smith template<typename T> struct X { A<T> auto f(); }; 4203a9683fcSRichard Smith template<typename T> A<T> auto X<T>::f() {} 4213a9683fcSRichard Smith } 422bfddbdafSErich Keane 423bfddbdafSErich Keane namespace GH65810 { 424bfddbdafSErich Keane template<typename Param> 425bfddbdafSErich Keane concept TrivialConcept = 426bfddbdafSErich Keane requires(Param param) { 427bfddbdafSErich Keane (void)param; 428bfddbdafSErich Keane }; 429bfddbdafSErich Keane 430bfddbdafSErich Keane template <typename T> 431bfddbdafSErich Keane struct Base { 432bfddbdafSErich Keane class InnerClass; 433bfddbdafSErich Keane }; 434bfddbdafSErich Keane 435bfddbdafSErich Keane template <typename T> 436bfddbdafSErich Keane class Base<T>::InnerClass { 437bfddbdafSErich Keane template <typename Param> 438bfddbdafSErich Keane requires TrivialConcept<Param> 439bfddbdafSErich Keane int func(Param param) const; 440bfddbdafSErich Keane }; 441bfddbdafSErich Keane 442bfddbdafSErich Keane template <typename T> 443bfddbdafSErich Keane template <typename Param> 444bfddbdafSErich Keane requires TrivialConcept<Param> 445bfddbdafSErich Keane int Base<T>::InnerClass::func(Param param) const { 446bfddbdafSErich Keane return 0; 447bfddbdafSErich Keane } 448bfddbdafSErich Keane 449bfddbdafSErich Keane template<typename T> 450bfddbdafSErich Keane struct Outermost { 451bfddbdafSErich Keane struct Middle { 452bfddbdafSErich Keane template<typename U> 453bfddbdafSErich Keane struct Innermost { 454bfddbdafSErich Keane template <typename Param> 455bfddbdafSErich Keane requires TrivialConcept<Param> 456bfddbdafSErich Keane int func(Param param) const; 457bfddbdafSErich Keane }; 458bfddbdafSErich Keane }; 459bfddbdafSErich Keane }; 460bfddbdafSErich Keane 461bfddbdafSErich Keane template <typename T> 462bfddbdafSErich Keane template <typename U> 463bfddbdafSErich Keane template <typename Param> 464bfddbdafSErich Keane requires TrivialConcept<Param> 465bfddbdafSErich Keane int Outermost<T>::Middle::Innermost<U>::func(Param param) const { 466bfddbdafSErich Keane return 0; 467bfddbdafSErich Keane } 468bfddbdafSErich Keane 469bfddbdafSErich Keane } // namespace GH65810 47098191d7cSErich Keane 47198191d7cSErich Keane namespace GH61763 { 47298191d7cSErich Keane template<typename T, typename U> 47398191d7cSErich Keane concept same_as = true; 47498191d7cSErich Keane 47598191d7cSErich Keane template <class = void> 47698191d7cSErich Keane struct Foo { 47798191d7cSErich Keane template <same_as<void> Param> 47898191d7cSErich Keane friend struct Bar; 47998191d7cSErich Keane }; 48098191d7cSErich Keane 48198191d7cSErich Keane template struct Foo<>; 48298191d7cSErich Keane 48398191d7cSErich Keane template <same_as<void> Param> 48498191d7cSErich Keane struct Bar { 48598191d7cSErich Keane }; 48698191d7cSErich Keane 48798191d7cSErich Keane 48898191d7cSErich Keane template<typename T> 48998191d7cSErich Keane concept ok = true; 49098191d7cSErich Keane 49198191d7cSErich Keane struct outer { 49298191d7cSErich Keane template<typename T> 49398191d7cSErich Keane requires ok<T> 49498191d7cSErich Keane struct foo {}; 49598191d7cSErich Keane }; 49698191d7cSErich Keane 49798191d7cSErich Keane template<typename U> 49898191d7cSErich Keane struct bar { 49998191d7cSErich Keane template<typename T> 50098191d7cSErich Keane requires ok<T> 50198191d7cSErich Keane friend struct outer::foo; 50298191d7cSErich Keane }; 50398191d7cSErich Keane 50498191d7cSErich Keane bar<int> x; 50598191d7cSErich Keane } // namespace GH61763 50698191d7cSErich Keane 507f5efa749SIlya Biryukov 508f5efa749SIlya Biryukov namespace GH74314 { 509f5efa749SIlya Biryukov template <class T, class U> constexpr bool is_same_v = __is_same(T, U); 510f5efa749SIlya Biryukov template <class T, class U> constexpr bool is_not_same_v = !__is_same(T, U); 511f5efa749SIlya Biryukov 512f5efa749SIlya Biryukov template <class Result> 513f5efa749SIlya Biryukov concept something_interesting = requires { 514f5efa749SIlya Biryukov true; 515f5efa749SIlya Biryukov requires is_same_v<int, Result>; 516f5efa749SIlya Biryukov }; 517f5efa749SIlya Biryukov 518f5efa749SIlya Biryukov template <class T> 5198282c58dSc8ef struct X { // #defined-here 520f5efa749SIlya Biryukov void foo() requires requires { requires is_not_same_v<T, int>; }; 521f5efa749SIlya Biryukov void bar(decltype(requires { requires is_not_same_v<T, int>; })); 522f5efa749SIlya Biryukov }; 523f5efa749SIlya Biryukov 524f5efa749SIlya Biryukov template <class T> 525f5efa749SIlya Biryukov void X<T>::foo() requires requires { requires something_interesting<T>; } {} 526f5efa749SIlya Biryukov // expected-error@-1{{definition of 'foo' does not match any declaration}} 5278282c58dSc8ef // expected-note@#defined-here{{defined here}} 5288282c58dSc8ef // expected-note@-8{{member declaration nearly matches}} 529f5efa749SIlya Biryukov 530f5efa749SIlya Biryukov template <class T> 531f5efa749SIlya Biryukov void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok 532f5efa749SIlya Biryukov 533f5efa749SIlya Biryukov template <class T> 534f5efa749SIlya Biryukov void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {} 535f5efa749SIlya Biryukov // expected-error@-1{{definition of 'bar' does not match any declaration}} 5368282c58dSc8ef // expected-note@#defined-here{{defined here}} 537f5efa749SIlya Biryukov 538f5efa749SIlya Biryukov template <class T> 539f5efa749SIlya Biryukov void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {} 540f5efa749SIlya Biryukov } // namespace GH74314 54104d20b17SYounan Zhang 542ab70ac60SYounan Zhang namespace GH56482 { 543ab70ac60SYounan Zhang template <typename SlotMap> 544ab70ac60SYounan Zhang concept slot_map_has_reserve = true; 545ab70ac60SYounan Zhang 546ab70ac60SYounan Zhang template <typename T> struct Slot_map { 547ab70ac60SYounan Zhang constexpr void reserve() const noexcept 548ab70ac60SYounan Zhang requires slot_map_has_reserve<Slot_map>; 549ab70ac60SYounan Zhang 550ab70ac60SYounan Zhang constexpr void reserve(int) const noexcept 551ab70ac60SYounan Zhang requires slot_map_has_reserve<Slot_map<T>>; 552ab70ac60SYounan Zhang }; 553ab70ac60SYounan Zhang 554ab70ac60SYounan Zhang template <typename T> 555ab70ac60SYounan Zhang constexpr void Slot_map<T>::reserve() const noexcept 556ab70ac60SYounan Zhang requires slot_map_has_reserve<Slot_map<T>> 557ab70ac60SYounan Zhang {} 558ab70ac60SYounan Zhang 559ab70ac60SYounan Zhang template <typename T> 560ab70ac60SYounan Zhang constexpr void Slot_map<T>::reserve(int) const noexcept 561ab70ac60SYounan Zhang requires slot_map_has_reserve<Slot_map> 562ab70ac60SYounan Zhang {} 563ab70ac60SYounan Zhang } // namespace GH56482 564ab70ac60SYounan Zhang 56504d20b17SYounan Zhang namespace GH74447 { 56604d20b17SYounan Zhang template <typename T> struct S { 56704d20b17SYounan Zhang template <typename... U, int V> 56804d20b17SYounan Zhang void test(T target, U... value) 56904d20b17SYounan Zhang requires requires { 57004d20b17SYounan Zhang target; 57104d20b17SYounan Zhang sizeof...(value) == 1; 57204d20b17SYounan Zhang V == 2; 57304d20b17SYounan Zhang }; 57404d20b17SYounan Zhang }; 57504d20b17SYounan Zhang 57604d20b17SYounan Zhang template <typename T> 57704d20b17SYounan Zhang template <typename... U, int V> 57804d20b17SYounan Zhang void S<T>::test(T target, U... value) 57904d20b17SYounan Zhang requires requires { 58004d20b17SYounan Zhang target; 58104d20b17SYounan Zhang sizeof...(value) == 1; 58204d20b17SYounan Zhang V == 2; 58304d20b17SYounan Zhang } 58404d20b17SYounan Zhang {} 58504d20b17SYounan Zhang } // namespace GH74447 5862c2d291bSYounan Zhang 5872c2d291bSYounan Zhang namespace GH72557 { 5882c2d291bSYounan Zhang 5892c2d291bSYounan Zhang template <typename...> 5902c2d291bSYounan Zhang concept IsAnyOf = true; 5912c2d291bSYounan Zhang 5922c2d291bSYounan Zhang template <class... DerTs> struct DerivedCollection { 5932c2d291bSYounan Zhang template <class DerT> 5942c2d291bSYounan Zhang requires IsAnyOf<DerTs...> 5952c2d291bSYounan Zhang unsigned long index(); 5962c2d291bSYounan Zhang }; 5972c2d291bSYounan Zhang 5982c2d291bSYounan Zhang template <class... DerTs> 5992c2d291bSYounan Zhang template <class DerT> 6002c2d291bSYounan Zhang requires IsAnyOf<DerTs...> 6012c2d291bSYounan Zhang unsigned long DerivedCollection<DerTs...>::index() {} 6022c2d291bSYounan Zhang 6032c2d291bSYounan Zhang } // namespace GH72557 604e6974daaSYounan Zhang 605e6974daaSYounan Zhang namespace GH101735 { 606e6974daaSYounan Zhang 607e6974daaSYounan Zhang template <class, class> 608e6974daaSYounan Zhang concept True = true; 609e6974daaSYounan Zhang 610e6974daaSYounan Zhang template <typename T> 611e6974daaSYounan Zhang class A { 612e6974daaSYounan Zhang template <typename... Ts> 613e6974daaSYounan Zhang void method(Ts&... ts) 614e6974daaSYounan Zhang requires requires (T t) { 615e6974daaSYounan Zhang { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; 616e6974daaSYounan Zhang }; 617e6974daaSYounan Zhang }; 618e6974daaSYounan Zhang 619e6974daaSYounan Zhang template <typename T> 620e6974daaSYounan Zhang template <typename... Ts> 621e6974daaSYounan Zhang void A<T>::method(Ts&... ts) 622e6974daaSYounan Zhang requires requires (T t) { 623e6974daaSYounan Zhang { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; 624e6974daaSYounan Zhang } {} 625e6974daaSYounan Zhang 626e6974daaSYounan Zhang } 627e32a62c0SBalazs Benics 628e32a62c0SBalazs Benics namespace GH63782 { 629e32a62c0SBalazs Benics // GH63782 was also fixed by PR #80594, so let's add a test for it. 630e32a62c0SBalazs Benics 631e32a62c0SBalazs Benics template<bool... Vals> 632e32a62c0SBalazs Benics constexpr bool All = (Vals && ...); 633e32a62c0SBalazs Benics 634e32a62c0SBalazs Benics template<bool... Bs> 635e32a62c0SBalazs Benics class Class { 636e32a62c0SBalazs Benics template<typename> 637e32a62c0SBalazs Benics requires All<Bs...> 638e32a62c0SBalazs Benics void Foo(); 639e32a62c0SBalazs Benics }; 640e32a62c0SBalazs Benics 641e32a62c0SBalazs Benics template<bool... Bs> 642e32a62c0SBalazs Benics template<typename> 643e32a62c0SBalazs Benics requires All<Bs...> 644e32a62c0SBalazs Benics void Class<Bs...>::Foo() { 645e32a62c0SBalazs Benics }; 646e32a62c0SBalazs Benics 647e32a62c0SBalazs Benics } // namespace GH63782 648e32a62c0SBalazs Benics 649e32a62c0SBalazs Benics namespace eve { 650e32a62c0SBalazs Benics // Reduced from the "eve" project 651e32a62c0SBalazs Benics 652e32a62c0SBalazs Benics template <typename... Ts> 653e32a62c0SBalazs Benics struct tuple { 654e32a62c0SBalazs Benics template <int I0> requires(I0 <= sizeof...(Ts)) 655e32a62c0SBalazs Benics constexpr auto split(); 656e32a62c0SBalazs Benics }; 657e32a62c0SBalazs Benics 658e32a62c0SBalazs Benics template <typename... Ts> 659e32a62c0SBalazs Benics template <int I0> 660e32a62c0SBalazs Benics requires(I0 <= sizeof...(Ts)) 661e32a62c0SBalazs Benics constexpr auto tuple<Ts...>::split(){ 662e32a62c0SBalazs Benics return 0; 663e32a62c0SBalazs Benics } 664e32a62c0SBalazs Benics 665e32a62c0SBalazs Benics int foo() { 666e32a62c0SBalazs Benics tuple<int, float> x; 667e32a62c0SBalazs Benics return x.split<0>(); 668e32a62c0SBalazs Benics } 669e32a62c0SBalazs Benics 670e32a62c0SBalazs Benics } // namespace eve 671463a4f15SYounan Zhang 672463a4f15SYounan Zhang namespace GH93099 { 673463a4f15SYounan Zhang 674463a4f15SYounan Zhang // Issues with sizeof...(expr) 675463a4f15SYounan Zhang 676463a4f15SYounan Zhang template <typename T = int> struct C { 677463a4f15SYounan Zhang template <int... N> 678463a4f15SYounan Zhang requires(sizeof...(N) > 0) 679463a4f15SYounan Zhang friend class NTTP; 680463a4f15SYounan Zhang 681463a4f15SYounan Zhang template <class... Tp> 682463a4f15SYounan Zhang requires(sizeof...(Tp) > 0) 683463a4f15SYounan Zhang friend class TP; 684463a4f15SYounan Zhang 685463a4f15SYounan Zhang template <template <typename> class... TTp> 686463a4f15SYounan Zhang requires(sizeof...(TTp) > 0) 687463a4f15SYounan Zhang friend class TTP; 688463a4f15SYounan Zhang }; 689463a4f15SYounan Zhang 690463a4f15SYounan Zhang template <int... N> 691463a4f15SYounan Zhang requires(sizeof...(N) > 0) 692463a4f15SYounan Zhang class NTTP; 693463a4f15SYounan Zhang 694463a4f15SYounan Zhang template <class... Tp> 695463a4f15SYounan Zhang requires(sizeof...(Tp) > 0) 696463a4f15SYounan Zhang class TP; 697463a4f15SYounan Zhang 698463a4f15SYounan Zhang template <template <typename> class... TTp> 699463a4f15SYounan Zhang requires(sizeof...(TTp) > 0) 700463a4f15SYounan Zhang class TTP; 701463a4f15SYounan Zhang 702463a4f15SYounan Zhang C v; 703463a4f15SYounan Zhang 704463a4f15SYounan Zhang } // namespace GH93099 705227afac3SYounan Zhang 70637b4df43SYounan Zhang namespace GH115098 { 70737b4df43SYounan Zhang 70837b4df43SYounan Zhang template <typename... Ts> struct c { 70937b4df43SYounan Zhang template <typename T> 71037b4df43SYounan Zhang requires(sizeof...(Ts) > 0) 71137b4df43SYounan Zhang friend bool operator==(c, c); 71237b4df43SYounan Zhang }; 71337b4df43SYounan Zhang 71437b4df43SYounan Zhang template <typename... Ts> struct d { 71537b4df43SYounan Zhang template <typename T> 71637b4df43SYounan Zhang requires(sizeof...(Ts) > 0) 71737b4df43SYounan Zhang friend bool operator==(d, d); 71837b4df43SYounan Zhang }; 71937b4df43SYounan Zhang 72037b4df43SYounan Zhang template struct c<int>; 72137b4df43SYounan Zhang template struct d<int, int>; 72237b4df43SYounan Zhang 72337b4df43SYounan Zhang } // namespace GH115098 72437b4df43SYounan Zhang 725*27c91730SYounan Zhang namespace GH123441 { 726*27c91730SYounan Zhang 727*27c91730SYounan Zhang struct buf { 728*27c91730SYounan Zhang constexpr buf(auto&&... initList) requires (sizeof...(initList) <= 8); 729*27c91730SYounan Zhang }; 730*27c91730SYounan Zhang 731*27c91730SYounan Zhang constexpr buf::buf(auto&&... initList) requires (sizeof...(initList) <= 8) {} 732*27c91730SYounan Zhang 733*27c91730SYounan Zhang template <class> 734*27c91730SYounan Zhang struct buffer { 735*27c91730SYounan Zhang constexpr buffer(auto&&... initList) requires (sizeof...(initList) <= 8); 736*27c91730SYounan Zhang }; 737*27c91730SYounan Zhang 738*27c91730SYounan Zhang template <class T> 739*27c91730SYounan Zhang constexpr buffer<T>::buffer(auto&&... initList) requires (sizeof...(initList) <= 8) {} 740*27c91730SYounan Zhang 741*27c91730SYounan Zhang template <class...> 742*27c91730SYounan Zhang struct foo { // expected-note {{foo defined here}} 743*27c91730SYounan Zhang constexpr foo(auto&&... initList) 744*27c91730SYounan Zhang requires (sizeof...(initList) <= 8); 745*27c91730SYounan Zhang }; 746*27c91730SYounan Zhang 747*27c91730SYounan Zhang template <class... T> 748*27c91730SYounan Zhang constexpr foo<T...>::foo(auto&&... initList) // expected-error {{does not match any declaration}} 749*27c91730SYounan Zhang requires (sizeof...(T) <= 8) {} 750*27c91730SYounan Zhang 751*27c91730SYounan Zhang } // namespace GH123441 752*27c91730SYounan Zhang 753227afac3SYounan Zhang namespace GH114685 { 754227afac3SYounan Zhang 755227afac3SYounan Zhang template <typename T> struct ptr { 756227afac3SYounan Zhang template <typename U> 757227afac3SYounan Zhang friend ptr<U> make_item(auto &&args) 758227afac3SYounan Zhang requires(sizeof(args) > 1); 759227afac3SYounan Zhang }; 760227afac3SYounan Zhang 761227afac3SYounan Zhang template <typename U> 762227afac3SYounan Zhang ptr<U> make_item(auto &&args) 763227afac3SYounan Zhang requires(sizeof(args) > 1) {} 764227afac3SYounan Zhang 765227afac3SYounan Zhang ptr<char> p; 766227afac3SYounan Zhang 767227afac3SYounan Zhang } // namespace GH114685 76869d0c4c1SYounan Zhang 76969d0c4c1SYounan Zhang namespace GH123472 { 77069d0c4c1SYounan Zhang 77169d0c4c1SYounan Zhang consteval bool fn() { return true; } 77269d0c4c1SYounan Zhang 77369d0c4c1SYounan Zhang struct S { 77469d0c4c1SYounan Zhang template <typename T> 77569d0c4c1SYounan Zhang static consteval void mfn() requires (bool(&fn)); 77669d0c4c1SYounan Zhang }; 77769d0c4c1SYounan Zhang 77869d0c4c1SYounan Zhang template <typename T> 77969d0c4c1SYounan Zhang consteval void S::mfn() requires (bool(&fn)) {} 78069d0c4c1SYounan Zhang 78169d0c4c1SYounan Zhang } 782