// RUN: %clang_cc1 -std=c++2c -verify %s template concept A = (T(), true); template concept C = A && true; // #C template concept D = A && __is_same(T, int); template requires (A) constexpr int f(T) { return 0; }; template requires (C && ...) constexpr int f(T...) { return 1; }; static_assert(f(0) == 0); static_assert(f(1) == 0); template requires (A && ...) constexpr int g(T...) { return 0; }; template requires (C && ...) constexpr int g(T...) { return 1; }; static_assert(g(0) == 1); static_assert(g() == 1); static_assert(g(1, 2) == 1); template requires (A && ...) constexpr int h(T...) { return 0; }; // expected-note {{candidate}} template requires (C || ...) constexpr int h(T...) { return 1; }; // expected-note {{candidate}} static_assert(h(0) == 1); // expected-error {{call to 'h' is ambiguous}} template requires (A || ...) constexpr int i(T...) { return 0; }; // expected-note {{candidate}} template requires (C && ...) constexpr int i(T...) { return 1; }; // expected-note {{candidate}} static_assert(i(0) == 1); // expected-error {{call to 'i' is ambiguous}} template requires (A || ... || true) constexpr int j(T...) { return 0; }; // #j1 template requires (C && ... && true) constexpr int j(T...) { return 1; }; // #j2 static_assert(j(0) == 1); // expected-error@-1 {{call to 'j' is ambiguous}} // expected-note@#j1 {{candidate function [with T = ]}} // expected-note@#j2 {{candidate function [with T = ]}} // expected-note@#j2 {{imilar constraint expressions not considered equivalent}} // expected-note@#j1 {{similar constraint expression here}} static_assert(j() == 1); // expected-error@-1 {{call to 'j' is ambiguous}} // expected-note@#j1 {{candidate function [with T = <>]}} // expected-note@#j2 {{candidate function [with T = <>]}} // expected-note@#j2 {{imilar constraint expressions not considered equivalent}} // expected-note@#j1 {{similar constraint expression here}} template requires (A || ...) constexpr int k(T...) { return 0; }; // expected-note {{candidate template ignored: constraints not satisfied [with T = <>]}} template requires (C || ...) constexpr int k(T...) { return 1; }; // expected-note {{candidate template ignored: constraints not satisfied [with T = <>]}} static_assert(k(0) == 1); static_assert(k() == 0); // expected-error {{no matching function for call to 'k'}} static_assert(k(1, 2) == 1); consteval int terse(A auto...) {return 1;} consteval int terse(D auto...) {return 2;} static_assert(terse() == 2); static_assert(terse(0, 0) == 2); static_assert(terse(0L, 0) == 1); template consteval int tpl_head(A auto...) {return 1;} template consteval int tpl_head(D auto...) {return 2;} static_assert(tpl_head() == 2); static_assert(tpl_head(0, 0) == 2); static_assert(tpl_head(0L, 0) == 1); namespace equivalence { template struct S { template void f() requires (A && ...); template void f() requires (C && ...); template void g() requires (A && ...); template void g() requires (C && ...); template void h() requires (A && ...); // expected-note {{candidate}} template void h() requires (C && ...); // expected-note {{candidate}} }; void test() { S{}.f(); S{}.g(); S{}.h(); // expected-error {{call to member function 'h' is ambiguous}} } } namespace substitution { struct S { using type = int; }; template consteval int And1() requires (C && ...) { // #and1 return 1; } template consteval int And2() requires (C && ... && C) { // #and2 return 2; } template consteval int And3() requires (C && ... && C) { // #and3 return 3; } template consteval int Or1() requires (C || ...) { // #or1 return 1; } template consteval int Or2() requires (C || ... || C) { // #or2 return 2; } template consteval int Or3() requires (C || ... || C) { // #or3 return 3; } static_assert(And1<>() == 1); static_assert(And1() == 1); static_assert(And1() == 1); // FIXME: The diagnostics are not so great static_assert(And1() == 1); // expected-error {{no matching function for call to 'And1'}} // expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = ]}} // expected-note@#and1 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And1() == 1); // expected-error {{no matching function for call to 'And1'}} // expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = ]}} // expected-note@#and1 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And1() == 1); // expected-error {{no matching function for call to 'And1'}} // expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = ]}} // expected-note@#and1 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And2() == 2); static_assert(And2() == 2); static_assert(And2() == 2); // expected-error {{no matching function for call to 'And2'}} // expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}} // expected-note@#and2 {{because 'typename U::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And2() == 2); // expected-error {{no matching function for call to 'And2'}} // expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = S, U = ]}} \ // expected-note@#and2 {{because 'typename U::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And2() == 2); // expected-error {{no matching function for call to 'And2'}} // expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = ]}} // expected-note@#and2 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And2() == 2); // expected-error {{no matching function for call to 'And2'}} // expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = ]}} // expected-note@#and2 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And3() == 3); static_assert(And3() == 3); static_assert(And3() == 3); // expected-error {{no matching function for call to 'And3'}} // expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}} // expected-note@#and3 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And3() == 3); // expected-error {{no matching function for call to 'And3'}} // expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = ]}} // expected-note@#and3 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And3() == 3); // expected-error {{no matching function for call to 'And3'}} // expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = S, U = ]}} // expected-note@#and3 {{because 'typename U::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(And3() == 3); // expected-error {{no matching function for call to 'And3'}} // expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = ]}} // expected-note@#and3 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(Or1<>() == 1); // expected-error {{no matching function for call to 'Or1'}} // expected-note@#or1 {{candidate template ignored: constraints not satisfied}} static_assert(Or1() == 1); static_assert(Or1() == 1); static_assert(Or1() == 1); static_assert(Or1() == 1); static_assert(Or1() == 1); // expected-error {{no matching function for call to 'Or1'}} // expected-note@#or1 {{candidate template ignored: constraints not satisfied}} // expected-note@#or1 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(Or2() == 2); static_assert(Or2() == 2); static_assert(Or2() == 2); static_assert(Or2() == 2); static_assert(Or2() == 2); // expected-error {{no matching function for call to 'Or2'}} // expected-note@#or2 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}} // expected-note@#or2 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} static_assert(Or3() == 3); static_assert(Or3() == 3); static_assert(Or3() == 3); static_assert(Or3() == 3); static_assert(Or3() == 3); // expected-error {{no matching function for call to 'Or3'}} // expected-note@#or3 {{candidate template ignored: constraints not satisfied}} // expected-note@#or3 {{because 'typename T::type' does not satisfy 'C'}} // expected-note@#C {{because 'T' does not satisfy 'A'}} } namespace bool_conversion_break { template struct A; struct Thingy { static constexpr int compare(const Thingy&) {return 1;} }; template void f(A *, A *) // expected-note {{candidate template ignored: constraints not satisfied}} requires (T::compare(U{}) && ...); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}} void g() { A *ap; f(ap, ap); // expected-error{{no matching function for call to 'f'}} \ // expected-note {{while checking constraint satisfaction}} \ // expected-note {{while substituting deduced template arguments}} } } namespace nested { template struct S { template consteval static int f() requires ((A && ...) && ... && A ) { return 1; } template consteval static int f() requires ((C && ...) && ... && C ) { return 2; } template consteval static int g() // #nested-ambiguous-g1 requires ((A && ...) && ... && A ) { return 1; } template consteval static int g() // #nested-ambiguous-g2 requires ((C && ...) && ... && C ) { return 2; } }; static_assert(S::f() == 2); static_assert(S::g() == 2); } namespace GH99430 { template using _Synth_three_way_result = int; template class tuple; template struct tuple_element; template struct _Three_way_comparison_result_with_tuple_like { using type = int; }; template requires(requires { typename _Synth_three_way_result<_TTypes, tuple_element<_Indices>>; } && ...) struct _Three_way_comparison_result_with_tuple_like, _Indices...>{ using type = long; }; static_assert(__is_same_as(_Three_way_comparison_result_with_tuple_like, 0, 1>::type, int)); static_assert(__is_same_as(_Three_way_comparison_result_with_tuple_like, 0>::type, long)); } namespace GH88866 { template struct index_by; template concept InitFunc = true; namespace ExpandsBoth { template auto... init> struct LazyLitMatrix; // expected-note {{here}} template < typename...Indices, InitFunc> auto... init > struct LazyLitMatrix, init...> { }; // FIXME: Explain why we didn't pick up the partial specialization - pack sizes don't match. template struct LazyLitMatrix, 42>; // expected-error@-1 {{instantiation of undefined template}} template struct LazyLitMatrix, 42, 43>; } namespace ExpandsRespectively { template auto... init> struct LazyLitMatrix; template < typename...Indices, InitFunc> auto... init > struct LazyLitMatrix, init...> { }; template struct LazyLitMatrix, 42>; template struct LazyLitMatrix, 42, 43>; } namespace TypeParameter { template ... init> struct LazyLitMatrix; // expected-note {{here}} template < typename...Indices, InitFunc>... init > struct LazyLitMatrix, init...> { }; // FIXME: Explain why we didn't pick up the partial specialization - pack sizes don't match. template struct LazyLitMatrix, float>; // expected-error@-1 {{instantiation of undefined template}} template struct LazyLitMatrix, unsigned, float>; } namespace Invalid { template ... init> struct LazyLitMatrix; template < typename...Indices, InitFunc> init // expected-error@-1 {{unexpanded parameter pack 'Indices'}} > struct LazyLitMatrix, init> { }; } } namespace GH135190 { template concept A = __is_same_as(T, int) || __is_same_as(T, double) ; template concept B = A && __is_same_as(T, double); template requires(A && ...) constexpr int g() { return 1; } template requires(B && ...) constexpr int g() { return 2; } static_assert(g() == 2); template concept all_A = (A && ...); template concept all_B = (B && ...); template requires all_A constexpr int h() { return 1; } template requires all_B constexpr int h() { return 2; } static_assert(h() == 2); } namespace parameter_mapping_regressions { namespace case1 { namespace std { template constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); template concept constructible_from = is_constructible_v<_Tp, _Args...>; template concept default_initializable = true; template using iterator_t = int; template concept view = constructible_from<_Tp, _Tp>; template requires(view<_Views> && ...) class zip_transform_view; } // namespace std struct IterDefaultCtrView {}; template using Iter = std::iterator_t>; static_assert( std::default_initializable>); } namespace case2 { template constexpr bool False = false; template concept __zip_all_random_access = (False<_Views> && ...); // expected-note@-1 {{evaluated to false}} template struct zip_view { void f() requires __zip_all_random_access<_Views...>{}; // expected-note@-1 {{because 'int' does not satisfy}} }; zip_view test_v; static_assert(!__zip_all_random_access); void test() { test_v.f(); // expected-error {{invalid reference to function 'f'}} } } }