diff options
Diffstat (limited to 'clang/test/CXX/temp/temp.fct.spec')
30 files changed, 1251 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp new file mode 100644 index 0000000..0aef6ad --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> struct A { }; + +template<typename T> T make(); +template<typename T> T make2(const T&); + +void test_make() { + int& ir0 = make<int&>(); + A<int> a0 = make< A<int> >(); + A<int> a1 = make2< A<int> >(A<int>()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp new file mode 100644 index 0000000..4d29b74 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace ParameterPacksWithFunctions { + template<typename ...> struct count; + + template<typename Head, typename ...Tail> + struct count<Head, Tail...> { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + template<unsigned> struct unsigned_c { }; + + template<typename ... Types> + unsigned_c<count<Types...>::value> f(); + + void test_f() { + unsigned_c<0> uc0a = f(); // okay, deduced to an empty pack + unsigned_c<0> uc0b = f<>(); + unsigned_c<1> uc1 = f<int>(); + unsigned_c<2> uc2 = f<float, double>(); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp new file mode 100644 index 0000000..de3b44f --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5811 +template <class F> void Call(F f) { f(1); } +template <typename T> void f(T); +void a() { Call(f<int>); } + +// Check the conversion of a template-id to a pointer +template<typename T, T* Address> struct Constant { }; +Constant<void(int), &f<int> > constant0; + +template<typename T, T* Address> void constant_func(); +void test_constant_func() { + constant_func<void(int), &f<int> >(); +} + + +// Check typeof() on a template-id referring to a single function +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +int typeof0[is_same<__typeof__(f<int>), void (int)>::value? 1 : -1]; +int typeof1[is_same<__typeof__(&f<int>), void (*)(int)>::value? 1 : -1]; + +template <typename T> void g(T); // expected-note{{possible target for call}} +template <typename T> void g(T, T); // expected-note{{possible target for call}} + +int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \ + // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp new file mode 100644 index 0000000..5556f35 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} + +void g() { + f<int,char*,double>("aa",3.0); // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int,char*>("aa",3.0); // Z is deduced to be double \ + // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int>("aa",3.0); // Y is deduced to be char*, and + // Z is deduced to be double + f("aa",3.0); // expected-error{{no matching}} +} + +// PR5910 +namespace PR5910 { + template <typename T> + void Func() {} + + template <typename R> + void Foo(R (*fp)()); + + void Test() { + Foo(Func<int>); + } +} + +// PR5949 +namespace PR5949 { + struct Bar; + + template <class Container> + void quuz(const Container &cont) { + } + + template<typename T> + int Foo(Bar *b, void (*Baz)(const T &t), T * = 0) { + return 0; + } + + template<typename T> + int Quux(Bar *b, T * = 0) + { + return Foo<T>(b, quuz); + } +} + +// PR7641 +namespace PR7641 { + namespace N2 + { + template<class> + int f0(int); + } + namespace N + { + using N2::f0; + } + + template<class R,class B1> + int + f1(R(a)(B1)); + + void f2() + { f1(N::f0<int>); } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp new file mode 100644 index 0000000..81addfe --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +// Test explicit specification of function template arguments. +void test_explicit_spec_simple() { + int *ip1 = first_arg<int *>(0); + int *ip2 = first_arg<int *, float*>(0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); +} + +// Template argument deduction can extend the sequence of template +// arguments corresponding to a template parameter pack, even when the +// sequence contains explicitly specified template arguments. +void test_explicit_spec_extension(double *dp) { + int *ip1 = first_arg<int *>(0, 0); + int *ip2 = first_arg<int *, float*>(0, 0, 0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); + int *i1 = second_arg<float *>(0, (int*)0, 0); + double *dp1 = first_arg<>(dp); +} + +template<typename ...Types> +struct tuple { }; + +template<typename ...Types> +void accept_tuple(tuple<Types...>); + +void test_explicit_spec_extension_targs(tuple<int, float, double> t3) { + accept_tuple(t3); + accept_tuple<int, float, double>(t3); + accept_tuple<int>(t3); + accept_tuple<int, float>(t3); +} + +template<typename R, typename ...ParmTypes> +void accept_function_ptr(R(*)(ParmTypes...)); + +void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) { + accept_function_ptr(f3); + accept_function_ptr<int>(f3); + accept_function_ptr<int, int>(f3); + accept_function_ptr<int, int, float>(f3); + accept_function_ptr<int, int, float, double>(f3); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp new file mode 100644 index 0000000..c14b063 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +#if !__has_feature(cxx_access_control_sfinae) +# error No support for access control as part of SFINAE? +#endif + +typedef char yes_type; +typedef char (&no_type)[2]; + +template<unsigned N> struct unsigned_c { }; + +template<typename T> +class has_copy_constructor { + static T t; + + template<typename U> static yes_type check(unsigned_c<sizeof(U(t))> * = 0); + template<typename U> static no_type check(...); + +public: + static const bool value = (sizeof(check<T>(0)) == sizeof(yes_type)); +}; + +struct HasCopy { }; + +struct HasNonConstCopy { + HasNonConstCopy(HasNonConstCopy&); +}; + +struct HasDeletedCopy { + HasDeletedCopy(const HasDeletedCopy&) = delete; +}; + +struct HasPrivateCopy { +private: + HasPrivateCopy(const HasPrivateCopy&); +}; + +int check0[has_copy_constructor<HasCopy>::value? 1 : -1]; +int check1[has_copy_constructor<HasNonConstCopy>::value? 1 : -1]; +int check2[has_copy_constructor<HasDeletedCopy>::value? -1 : 1]; +int check3[has_copy_constructor<HasPrivateCopy>::value? -1 : 1]; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp new file mode 100644 index 0000000..c27261c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <int> int f(int); // expected-note 2{{candidate}} +template <signed char> int f(int); // expected-note 2{{candidate}} +int i1 = f<1>(0); // expected-error{{ambiguous}} +int i2 = f<1000>(0); // expected-error{{ambiguous}} + +namespace PR6707 { + template<typename T, T Value> + struct X { }; + + template<typename T, T Value> + void f(X<T, Value>); + + void g(X<int, 10> x) { + f(x); + } + + static const unsigned char ten = 10; + template<typename T, T Value, typename U> + void f2(X<T, Value>, X<U, Value>); + + void g2() { + f2(X<int, 10>(), X<char, ten>()); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp new file mode 100644 index 0000000..6481485 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -verify %s + +typedef char one_byte; +struct two_bytes { char data[2]; }; + +template<typename T> one_byte __is_class_check(int T::*); +template<typename T> two_bytes __is_class_check(...); + +template<typename T> struct is_class { + static const bool value = sizeof(__is_class_check<T>(0)) == 1; +}; + +struct X { }; + +int array0[is_class<X>::value? 1 : -1]; +int array1[is_class<int>::value? -1 : 1]; +int array2[is_class<char[3]>::value? -1 : 1]; + +namespace instantiation_order1 { + template<typename T> + struct it_is_a_trap { + typedef typename T::trap type; + }; + + template<bool, typename T = void> + struct enable_if { + typedef T type; + }; + + template<typename T> + struct enable_if<false, T> { }; + + template<typename T> + typename enable_if<sizeof(T) == 17>::type + f(const T&, typename it_is_a_trap<T>::type* = 0); + + void f(...); + + void test_f() { + f('a'); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp new file mode 100644 index 0000000..90d2949 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +template<typename T> A<T> f0(T*); + +void test_f0(int *ip, float const *cfp) { + A<int> a0 = f0(ip); + A<const float> a1 = f0(cfp); +} + +template<typename T> void f1(T*, int); + +void test_f1(int *ip, float fv) { + f1(ip, fv); +} + +// TODO: this diagnostic can and should improve +template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \ +// expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}} + +struct ConvToIntPtr { + operator int*() const; +}; + +void test_f2(int *ip, float *fp) { + f2(ip, ConvToIntPtr()); // expected-error{{no matching function}} + f2(ip, ip); // okay + f2(ip, fp); // expected-error{{no matching function}} +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp new file mode 100644 index 0000000..8b192fa --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename T, typename U> struct pair { }; +template<typename T, typename U> pair<T, U> make_pair(T, U); + +// For a function parameter pack that occurs at the end of the +// parameter-declaration-list, the type A of each remaining argument +// of the call is compared with the type P of the declarator-id of the +// function parameter pack. +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +void test_simple_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg(ip); + int *ip2 = first_arg(ip, fp); + int *ip3 = first_arg(ip, fp, dp); + no_type nt1 = first_arg(); +} + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg_ref(Args&...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg_ref(Args&...); + +void test_simple_ref_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_ref(ip); + int *ip2 = first_arg_ref(ip, fp); + int *ip3 = first_arg_ref(ip, fp, dp); + no_type nt1 = first_arg_ref(); +} + + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: failed template argument deduction}} + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); + +void test_pair_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_pair(make_pair(ip, 17)); + int *ip2 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + int *ip3 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + float *fp1 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + float *fp2 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + no_type nt1 = first_arg_pair(); + no_type nt2 = second_arg_pair(); + no_type nt3 = second_arg_pair(make_pair(ip, 17)); + + + first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}} +} + +// For a function parameter pack that does not occur at the end of the +// parameter-declaration-list, the type of the parameter pack is a +// non-deduced context. +template<typename ...Types> struct tuple { }; + +template<typename ...Types> +void pack_not_at_end(tuple<Types...>, Types... values, int); + +void test_pack_not_at_end(tuple<int*, double*> t2) { + pack_not_at_end(t2, 0, 0, 0); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp new file mode 100644 index 0000000..c165c45 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct A { }; + +// bullet 1 +template<typename T> A<T> f0(T* ptr); + +void test_f0_bullet1() { + int arr0[6]; + A<int> a0 = f0(arr0); + const int arr1[] = { 1, 2, 3, 4, 5 }; + A<const int> a1 = f0(arr1); +} + +// bullet 2 +int g0(int, int); +float g1(float); + +void test_f0_bullet2() { + A<int(int, int)> a0 = f0(g0); + A<float(float)> a1 = f0(g1); +} + +// bullet 3 +struct X { }; +const X get_X(); + +template<typename T> A<T> f1(T); + +void test_f1_bullet3() { + A<X> a0 = f1(get_X()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp new file mode 100644 index 0000000..e470dd0 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + + +// If P is an rvalue reference to a cv-unqualified template parameter +// and the argument is an lvalue, the type "lvalue reference to A" is +// used in place of A for type deduction. +template<typename T> struct X { }; + +template<typename T> X<T> f0(T&&); + +struct Y { }; + +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +void test_f0() { + X<int> xi0 = f0(prvalue<int>()); + X<int> xi1 = f0(xvalue<int>()); + X<int&> xi2 = f0(lvalue<int>()); + X<Y> xy0 = f0(prvalue<Y>()); + X<Y> xy1 = f0(xvalue<Y>()); + X<Y&> xy2 = f0(lvalue<Y>()); +} + +template<typename T> X<T> f1(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} \ +// expected-note{{candidate function [with T = Y] not viable: no known conversion from 'Y' to 'const Y &&' for 1st argument}} + +void test_f1() { + X<int> xi0 = f1(prvalue<int>()); + X<int> xi1 = f1(xvalue<int>()); + f1(lvalue<int>()); // expected-error{{no matching function for call to 'f1'}} + X<Y> xy0 = f1(prvalue<Y>()); + X<Y> xy1 = f1(xvalue<Y>()); + f1(lvalue<Y>()); // expected-error{{no matching function for call to 'f1'}} +} + +namespace std_example { + template <class T> int f(T&&); + template <class T> int g(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} + + int i; + int n1 = f(i); + int n2 = f(0); + int n3 = g(i); // expected-error{{no matching function for call to 'g'}} +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp new file mode 100644 index 0000000..295f080 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +// Top-level cv-qualifiers of P's type are ignored for type deduction. +template<typename T> A<T> f0(const T); + +void test_f0(int i, const int ci) { + A<int> a0 = f0(i); + A<int> a1 = f0(ci); +} + +// If P is a reference type, the type referred to by P is used for type +// deduction. +template<typename T> A<T> f1(T&); + +void test_f1(int i, const int ci, volatile int vi) { + A<int> a0 = f1(i); + A<const int> a1 = f1(ci); + A<volatile int> a2 = f1(vi); +} + +template<typename T, unsigned N> struct B { }; +template<typename T, unsigned N> B<T, N> g0(T (&array)[N]); +template<typename T, unsigned N> B<T, N> g0b(const T (&array)[N]); + +void test_g0() { + int array0[5]; + B<int, 5> b0 = g0(array0); + const int array1[] = { 1, 2, 3}; + B<const int, 3> b1 = g0(array1); + B<int, 3> b2 = g0b(array1); +} + +template<typename T> B<T, 0> g1(const A<T>&); + +void test_g1(A<float> af) { + B<float, 0> b0 = g1(af); + B<int, 0> b1 = g1(A<int>()); +} + +// - If the original P is a reference type, the deduced A (i.e., the type +// referred to by the reference) can be more cv-qualified than the +// transformed A. +template<typename T> A<T> f2(const T&); + +void test_f2(int i, const int ci, volatile int vi) { + A<int> a0 = f2(i); + A<int> a1 = f2(ci); + A<volatile int> a2 = f2(vi); +} + +// PR5913 +template <typename T, int N> +void Foo(const T (&a)[N]) { + T x; + x = 0; +} + +const int a[1] = { 0 }; + +void Test() { + Foo(a); +} + +// - The transformed A can be another pointer or pointer to member type that +// can be converted to the deduced A via a qualification conversion (4.4). +template<typename T> A<T> f3(T * * const * const); + +void test_f3(int ***ip, volatile int ***vip) { + A<int> a0 = f3(ip); + A<volatile int> a1 = f3(vip); +} + +// Also accept conversions for pointer types which require removing +// [[noreturn]]. +namespace noreturn_stripping { + template <class R> + void f(R (*function)()); + + void g() __attribute__ ((__noreturn__)); + void h(); + void test() { + f(g); + f(h); + } +} + +// - If P is a class, and P has the form template-id, then A can be a +// derived class of the deduced A. Likewise, if P is a pointer to a class +// of the form template-id, A can be a pointer to a derived class pointed +// to by the deduced A. +template<typename T, int I> struct C { }; + +struct D : public C<int, 1> { }; +struct E : public D { }; +struct F : A<float> { }; +struct G : A<float>, C<int, 1> { }; + +template<typename T, int I> + C<T, I> *f4a(const C<T, I>&); +template<typename T, int I> + C<T, I> *f4b(C<T, I>); +template<typename T, int I> + C<T, I> *f4c(C<T, I>*); +int *f4c(...); + +void test_f4(D d, E e, F f, G g) { + C<int, 1> *ci1a = f4a(d); + C<int, 1> *ci2a = f4a(e); + C<int, 1> *ci1b = f4b(d); + C<int, 1> *ci2b = f4b(e); + C<int, 1> *ci1c = f4c(&d); + C<int, 1> *ci2c = f4c(&e); + C<int, 1> *ci3c = f4c(&g); + int *ip1 = f4c(&f); +} + +// PR8462 +namespace N { + struct T0; + struct T1; + + template<typename X, typename Y> struct B {}; + + struct J : B<T0,T0> {}; + struct K : B<T1,T1> {}; + + struct D : J, K {}; + + template<typename X, typename Y> void F(B<Y,X>); + + void test() + { + D d; + N::F<T0>(d); // Fails + N::F<T1>(d); // OK + } +} + +namespace PR9233 { + template<typename T> void f(const T **q); // expected-note{{candidate template ignored: substitution failure [with T = int]}} + + void g(int **p) { + f(p); // expected-error{{no matching function for call to 'f'}} + } + +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp new file mode 100644 index 0000000..83b5f23 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8598 { + template<class T> struct identity { typedef T type; }; + + template<class T, class C> + void f(T C::*, typename identity<T>::type*){} + + struct X { void f() {}; }; + + void g() { (f)(&X::f, 0); } +} + +namespace PR12132 { + template<typename S> void fun(const int* const S::* member) {} + struct A { int* x; }; + void foo() { + fun(&A::x); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp new file mode 100644 index 0000000..8b18189 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{candidate template ignored: deduced conflicting types for parameter 'T'}}\ + // expected-note {{no overload of 'temp2' matching 'void (*)(int)'}} + + template<class A> void temp(A); + void test0() { + // okay: deduce T=int from first argument, A=int during overload + apply(0, &temp); + apply(0, &temp<>); + + // okay: deduce T=int from first and second arguments + apply(0, &temp<int>); + + // deduction failure: T=int from first, T=long from second + apply(0, &temp<long>); // expected-error {{no matching function for call to 'apply'}} + } + + void over(int); + int over(long); + + void test1() { + // okay: deductions match + apply(0, &over); + + // deduction failure: deduced T=long from first argument, T=int from second + apply(0L, &over); // expected-error {{no matching function for call to 'apply'}} + } + + void over(short); + + void test2() { + // deduce T=int from first arg, second arg is undeduced context, + // pick correct overload of 'over' during overload resolution for 'apply' + apply(0, &over); + } + + template<class A, class B> B temp2(A); + void test3() { + // deduce T=int from first arg, A=int B=void during overload resolution + apply(0, &temp2); + apply(0, &temp2<>); + apply(0, &temp2<int>); + + // overload failure + apply(0, &temp2<long>); // expected-error {{no matching function for call to 'apply'}} + } +} + +namespace test1 { + template<class T> void invoke(void (*f)(T)) { f(T()); } // expected-note 6 {{couldn't infer template argument}} \ + // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} + + template<class T> void temp(T); + void test0() { + // deduction failure: overload has template => undeduced context + invoke(&temp); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp<>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp<int>); + } + + void over(int); + int over(long); + + void test1() { + // okay: only one overload matches + invoke(&over); + } + + void over(short); + + void test2() { + // deduction failure: overload has multiple matches => undeduced context + invoke(&over); // expected-error {{no matching function for call to 'invoke'}} + } + + template<class A, class B> B temp2(A); + void test3() { + // deduction failure: overload has template => undeduced context + // (even though partial application temp2<int> could in theory + // let us infer T=int) + invoke(&temp2); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<>); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<int>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp2<int, void>); + + // overload failure + invoke(&temp2<int, int>); // expected-error {{no matching function for call to 'invoke'}} + } +} + +namespace rdar8360106 { + template<typename R, typename T> void f0(R (*)(T), T); + template<typename R, typename T> void f1(R (&)(T) , T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + template<typename R, typename T> void f2(R (* const&)(T), T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + + int g(int); + int g(int, int); + + void h() { + f0(g, 1); + f0(&g, 1); + f1(g, 1); + f1(&g, 1); // expected-error{{no matching function for call to 'f1'}} + f2(g, 1); // expected-error{{no matching function for call to 'f2'}} + f2(&g, 1); + } +} + +namespace PR11713 { + template<typename T> + int f(int, int, int); + + template<typename T> + float f(float, float); + + template<typename R, typename B1, typename B2, typename A1, typename A2> + R& g(R (*)(B1, B2), A1, A2); + + void h() { + float &fr = g(f<int>, 1, 2); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp new file mode 100644 index 0000000..5a9ea08 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: [temp.deduct.conv]p2 bullets 1 and 2 can't actually happen without +// references? +// struct ConvertibleToArray { +// // template<typename T, unsigned N> +// // operator T(()[]) const; + +// private: +// typedef int array[17]; + +// operator array() const; +// }; + +// void test_array(ConvertibleToArray cta) { +// int *ip = cta; +// ip = cta; +// const float *cfp = cta; +// } + +// bullet 2 +// struct ConvertibleToFunction { +// template<typename T, typename A1, typename A2> +// operator T(A1, A2) const () { }; +// }; + +// bullet 3 +struct ConvertibleToCVQuals { + template<typename T> + operator T* const() const; +}; + +void test_cvqual_conv(ConvertibleToCVQuals ctcv) { + int *ip = ctcv; + const int *icp = ctcv; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp new file mode 100644 index 0000000..e23e98a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct AnyPtr { + template<typename T> + operator T*() const; +}; + +// If A is a cv-qualified type, the top level cv-qualifiers of A's type +// are ignored for type deduction. +void test_cvquals(AnyPtr ap) { + int* const ip = ap; + const float * const volatile fp = ap; +} + +// If A is a reference type, the type referred to by A is used for +// type deduction. +void test_ref_arg(AnyPtr ap) { + const int* const &ip = ap; + double * const &dp = ap; +} + +struct AnyRef { + template<typename T> + operator T&() const; +}; + +void test_ref_param(AnyRef ar) { + int &ir = ar; + const float &fr = ar; + int i = ar; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp new file mode 100644 index 0000000..4dca820 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +struct AnyT { + template<typename T> + operator T(); +}; + +void test_cvqual_ref(AnyT any) { + const int &cir = any; +} + +struct AnyThreeLevelPtr { + template<typename T> + operator T***() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type + // (EDG and GCC get this wrong) + return 0; + } +}; + +struct X { }; + +void test_deduce_with_qual(AnyThreeLevelPtr a3) { + int * const * const * const ip = a3; +} + +struct AnyPtrMem { + template<typename Class, typename T> + operator T Class::*() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type. + // (EDG and GCC get this wrong) + return 0; + } +}; + +void test_deduce_ptrmem_with_qual(AnyPtrMem apm) { + const float X::* pm = apm; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp new file mode 100644 index 0000000..99a265a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> + T f0(T, int); + +void test_f0() { + int (*f0a)(int, int) = f0; + int (*f0b)(int, int) = &f0; + float (*f0c)(float, int) = &f0; +} + +template<typename T> T f1(T, int); +template<typename T> T f1(T); + +void test_f1() { + float (*f1a)(float, int) = f1; + float (*f1b)(float, int) = &f1; + float (*f1c)(float) = f1; + float (*f1d)(float) = (f1); + float (*f1e)(float) = &f1; + float (*f1f)(float) = (&f1); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp new file mode 100644 index 0000000..01155e1 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> T* f(int); // #1 +template <class T, class U> T& f(U); // #2 + +void g() { + int *ip = f<int>(1); // calls #1 +} + +template<typename T> +struct identity { + typedef T type; +}; + +template <class T> + T* f2(int, typename identity<T>::type = 0); +template <class T, class U> + T& f2(U, typename identity<T>::type = 0); + +void g2() { + int* ip = f2<int>(1); +} + +template<class T, class U> struct A { }; + +template<class T, class U> inline int *f3( U, A<U,T>* p = 0 ); // #1 expected-note{{candidate function [with T = int, U = int]}} +template< class U> inline float *f3( U, A<U,U>* p = 0 ); // #2 expected-note{{candidate function [with U = int]}} + +void g3() { + float *fp = f3<int>( 42, (A<int,int>*)0 ); // Ok, picks #2. + f3<int>( 42 ); // expected-error{{call to 'f3' is ambiguous}} + +} + +namespace PR9006 { + struct X { + template <class Get> + int &f(char const* name, Get fget, char const* docstr = 0); + + template <class Get, class Set> + float &f(char const* name, Get fget, Set fset, char const* docstr = 0); + }; + + void test(X x) { + int &ir = x.f("blah", 0, "blah"); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp new file mode 100644 index 0000000..b965300 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Note: Partial ordering of function templates containing template +// parameter packs is independent of the number of deduced arguments +// for those template parameter packs. +template<class ...> struct Tuple { }; +template<class ... Types> int &g(Tuple<Types ...>); // #1 +template<class T1, class ... Types> float &g(Tuple<T1, Types ...>); // #2 +template<class T1, class ... Types> double &g(Tuple<T1, Types& ...>); // #3 + +void test_g() { + int &ir1 = g(Tuple<>()); + float &fr1 = g(Tuple<int, float>()); + double &dr1 = g(Tuple<int, float&>()); + double &dr2 = g(Tuple<int>()); +} + +template<class ... Types> int &h(int (*)(Types ...)); // #1 +template<class T1, class ... Types> float &h(int (*)(T1, Types ...)); // #2 +template<class T1, class ... Types> double &h(int (*)(T1, Types& ...)); // #3 + +void test_h() { + int &ir1 = h((int(*)())0); + float &fr1 = h((int(*)(int, float))0); + double &dr1 = h((int(*)(int, float&))0); + double &dr2 = h((int(*)(int))0); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp new file mode 100644 index 0000000..f204caf --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> int &f0(T&); +template<typename T> float &f0(T&&); + +// Core issue 1164 +void test_f0(int i) { + int &ir0 = f0(i); + float &fr0 = f0(5); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp new file mode 100644 index 0000000..8183061 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +template<typename T> void f(T&&); +template<> void f(int&) { } +void (*fp)(int&) = &f; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp new file mode 100644 index 0000000..bf5f962 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int i> class A { }; +template<short s> void f(A<s>); // expected-note{{candidate template ignored: substitution failure}} + +void k1() { + A<1> a; + f(a); // expected-error{{no matching function for call}} + f<1>(a); +} +template<const short cs> class B { }; +template<short s> void g(B<s>); +void k2() { + B<1> b; + g(b); // OK: cv-qualifiers are ignored on template parameter types +} + +template<short s> void h(int (&)[s]); // expected-note{{candidate function template not viable: requires 1 argument, but 2 were provided}} +void k3() { + int array[5]; + h(array); + h<5>(array); +} + +template<short s> void h(int (&)[s], A<s>); // expected-note{{candidate template ignored: substitution failure}} +void k4() { + A<5> a; + int array[5]; + h(array, a); // expected-error{{no matching function for call}} + h<5>(array, a); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp new file mode 100644 index 0000000..5b031c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If type deduction cannot be done for any P/A pair, or if for any +// pair the deduction leads to more than one possible set of deduced +// values, or if different pairs yield different deduced values, or if +// any template argument remains neither deduced nor explicitly +// specified, template argument deduction fails. + +template<typename ...> struct tuple; + +template<typename T, typename U> +struct same_tuple { + static const bool value = false; +}; + +template<typename ...Types1> +struct same_tuple<tuple<Types1...>, tuple<Types1...> > { + static const bool value = true; +}; + +int same_tuple_check1[same_tuple<tuple<int, float>, tuple<int, double>>::value? -1 : 1]; +int same_tuple_check2[same_tuple<tuple<float, double>, tuple<float, double>>::value? 1 : -1]; + diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp new file mode 100644 index 0000000..4e98a6d --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Note: Template argument deduction involving parameter packs +// (14.5.3) can deduce zero or more arguments for each parameter pack. + +template<class> struct X { + static const unsigned value = 0; +}; + +template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { + static const unsigned value = 1; +}; + +template<class ... Types> struct Y { + static const unsigned value = 0; +}; + +template<class T, class ... Types> struct Y<T, Types& ...> { + static const unsigned value = 1; +}; + +template<class ... Types> int f(void (*)(Types ...)); +void g(int, float); + +int check0[X<int>::value == 0? 1 : -1]; // uses primary template +int check1[X<int(int, float, double)>::value == 1? 1 : -1]; // uses partial specialization +int check2[X<int(float, int)>::value == 0? 1 : -1]; // uses primary template +int check3[Y<>::value == 0? 1 : -1]; // uses primary template +int check4[Y<int&, float&, double&>::value == 1? 1 : -1]; // uses partial specialization +int check5[Y<int, float, double>::value == 0? 1 : -1]; // uses primary template +int fv = f(g); // okay diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp new file mode 100644 index 0000000..fcc6cf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the original function parameter associated with A is a function +// parameter pack and the function parameter associated with P is not +// a function parameter pack, then template argument deduction fails. +template<class ... Args> int& f(Args ... args); +template<class T1, class ... Args> float& f(T1 a1, Args ... args); +template<class T1, class T2> double& f(T1 a1, T2 a2); + +void test_f() { + int &ir1 = f(); + float &fr1 = f(1, 2, 3); + double &dr1 = f(1, 2); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp new file mode 100644 index 0000000..c819d97 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// FIXME: More bullets to go! + +template<typename T, typename U> +struct has_nondeduced_pack_test { + static const bool value = false; +}; + +template<typename R, typename FirstType, typename ...Types> +struct has_nondeduced_pack_test<R(FirstType, Types..., int), + R(FirstType, Types...)> { + static const bool value = true; +}; + +// - A function parameter pack that does not occur at the end of the +// parameter-declaration-clause. +int check_nondeduced_pack_test0[ + has_nondeduced_pack_test<int(float, double, int), + int(float, double)>::value? 1 : -1]; + + diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp new file mode 100644 index 0000000..a6b1172 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Deductions specific to C++0x. + +template<typename T> +struct member_pointer_kind { + static const unsigned value = 0; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...)> { + static const unsigned value = 1; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &> { + static const unsigned value = 2; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &&> { + static const unsigned value = 3; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const> { + static const unsigned value = 4; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &> { + static const unsigned value = 5; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &&> { + static const unsigned value = 6; +}; + +struct X { }; + +static_assert(member_pointer_kind<int (X::*)(int)>::value == 1, ""); +static_assert(member_pointer_kind<int (X::*)(int) &>::value == 2, ""); +static_assert(member_pointer_kind<int (X::*)(int) &&>::value == 3, ""); +static_assert(member_pointer_kind<int (X::*)(int) const>::value == 4, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&>::value == 5, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&&>::value == 6, ""); diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp new file mode 100644 index 0000000..7774b5c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename ...Types> struct tuple; +template<unsigned> struct unsigned_c; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +namespace PackExpansionNotAtEnd { + template<typename T, typename U> + struct tuple_same_with_int { + static const bool value = false; + }; + + template<typename ...Types> + struct tuple_same_with_int<tuple<Types...>, tuple<Types..., int>> { + static const bool value = true; + }; + + int tuple_same_with_int_1[tuple_same_with_int<tuple<int, float, double>, + tuple<int, float, double, int> + >::value? 1 : -1]; + + template<typename ... Types> struct UselessPartialSpec; + + template<typename ... Types, // expected-note{{non-deducible template parameter 'Types'}} + typename Tail> // expected-note{{non-deducible template parameter 'Tail'}} + struct UselessPartialSpec<Types..., Tail>; // expected-warning{{class template partial specialization contains template parameters that can not be deduced; this partial specialization will never be used}} +} + +namespace DeduceNonTypeTemplateArgsInArray { + template<typename ...ArrayTypes> + struct split_arrays; + + template<typename ...ElementTypes, unsigned ...Bounds> + struct split_arrays<ElementTypes[Bounds]...> { + typedef tuple<ElementTypes...> element_types; + + // FIXME: Would like to have unsigned_tuple<Bounds...> here. + typedef tuple<unsigned_c<Bounds>...> bounds_types; + }; + + int check1[is_same<split_arrays<int[1], float[2], double[3]>::element_types, + tuple<int, float, double>>::value? 1 : -1]; + int check2[is_same<split_arrays<int[1], float[2], double[3]>::bounds_types, + tuple<unsigned_c<1>, unsigned_c<2>, unsigned_c<3>> + >::value? 1 : -1]; +} |