summaryrefslogtreecommitdiff
path: root/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp')
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
new file mode 100644
index 0000000..21aa24f
--- /dev/null
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -0,0 +1,251 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+template<typename T, T ...Values> struct value_tuple {};
+template<typename...> struct tuple { };
+template<typename T, typename U> struct pair { };
+
+template<typename T, T Value> struct value_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;
+};
+
+template<typename T>
+struct X0 {
+ template<T ...Values>
+ void f(value_tuple<T, Values...> * = 0);
+};
+
+void test_X0() {
+ X0<int>().f<1, 2, 3, 4, 5>();
+}
+
+namespace PacksAtDifferentLevels {
+
+ template<typename ...Types>
+ struct X {
+ template<typename> struct Inner {
+ static const unsigned value = 1;
+ };
+
+ template<typename ...YTypes>
+ struct Inner<tuple<pair<Types, YTypes>...> > {
+ static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
+ };
+ };
+
+ int check0[X<short, int, long>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>
+ >::value == 0? 1 : -1];
+
+ int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>
+ >::value == 1? 1 : -1];
+
+ template<unsigned ...Values> struct unsigned_tuple { };
+ template<typename ...Types>
+ struct X1 {
+ template<typename, typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<typename ...YTypes>
+ struct Inner<tuple<pair<Types, YTypes>...>,
+ unsigned_tuple<sizeof(Types) + sizeof(YTypes)...>> {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check2[X1<short, int, long>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ unsigned_tuple<sizeof(short) + sizeof(unsigned short),
+ sizeof(int) + sizeof(unsigned int),
+ sizeof(long) + sizeof(unsigned long)>
+ >::value == 1? 1 : -1];
+ int check3[X1<short, int>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ unsigned_tuple<sizeof(short) + sizeof(unsigned short),
+ sizeof(int) + sizeof(unsigned int),
+ sizeof(long) + sizeof(unsigned long)>
+ >::value == 0? 1 : -1];
+
+ template<typename ...Types>
+ struct X2 {
+ template<typename> struct Inner {
+ static const unsigned value = 1;
+ };
+
+ template<typename R, typename ...YTypes>
+ struct Inner<R(pair<Types, YTypes>...)> {
+ static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
+ };
+ };
+
+ int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>)
+ >::value == 0? 1 : -1];
+
+ int check5[X2<short, int>::Inner<int(pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>)
+ >::value == 1? 1 : -1];
+
+ template<typename T, typename U>
+ struct some_function_object {
+ template<typename>
+ struct result_of;
+ };
+
+ template<template<class> class...> struct metafun_tuple { };
+
+ template<typename ...Types1>
+ struct X3 {
+ template<typename, typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<typename ...Types2>
+ struct Inner<tuple<pair<Types1, Types2>...>,
+ metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ metafun_tuple<
+ some_function_object<short, unsigned short>::result_of,
+ some_function_object<int, unsigned int>::result_of,
+ some_function_object<long, unsigned long>::result_of>
+ >::value == 1? 1 : -1];
+ int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>,
+ pair<int, unsigned int>,
+ pair<long, unsigned long>>,
+ metafun_tuple<
+ some_function_object<short, unsigned short>::result_of,
+ some_function_object<int, unsigned int>::result_of,
+ some_function_object<long, unsigned long>::result_of>
+ >::value == 0? 1 : -1];
+
+ template<unsigned I, unsigned J> struct unsigned_pair { };
+
+ template<unsigned ...Values1>
+ struct X4 {
+ template<typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<unsigned ...Values2>
+ struct Inner<tuple<unsigned_pair<Values1, Values2>...>> {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check8[X4<1, 3, 5>::Inner<tuple<unsigned_pair<1, 2>,
+ unsigned_pair<3, 4>,
+ unsigned_pair<5, 6>>
+ >::value == 1? 1 : -1];
+ int check9[X4<1, 3>::Inner<tuple<unsigned_pair<1, 2>,
+ unsigned_pair<3, 4>,
+ unsigned_pair<5, 6>>
+ >::value == 0? 1 : -1];
+
+ template<class> struct add_reference;
+ template<class> struct add_pointer;
+ template<class> struct add_const;
+
+ template<template<class> class ...Templates>
+ struct X5 {
+ template<typename> struct Inner {
+ static const unsigned value = 0;
+ };
+
+ template<typename ...Types>
+ struct Inner<tuple<Templates<Types>...>> {
+ static const unsigned value = 1;
+ };
+ };
+
+ int check10[X5<add_reference, add_pointer, add_const>
+ ::Inner<tuple<add_reference<int>,
+ add_pointer<float>,
+ add_const<double>>>::value == 1? 1 : -1];
+ int check11[X5<add_reference, add_pointer>
+ ::Inner<tuple<add_reference<int>,
+ add_pointer<float>,
+ add_const<double>>>::value == 0? 1 : -1];
+
+}
+
+namespace ExpandingNonTypeTemplateParameters {
+ template<typename ...Types>
+ struct tuple_of_values {
+ template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \
+ // expected-note{{template parameter is declared here}}
+ struct apply { // expected-note 2{{template is declared here}}
+ typedef tuple<value_c<Types, Values>...> type;
+ };
+ };
+
+ int i;
+ float f;
+ int check_tuple_of_values_1[
+ is_same<tuple_of_values<int&, float&, char, int>::apply<i, f, 'a', 17>
+ ::type,
+ tuple<value_c<int&, i>, value_c<float&, f>, value_c<char, 'a'>,
+ value_c<int, 17>>
+ >::value? 1 : -1];
+
+ tuple_of_values<int, float> tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values<int, float>' requested here}}
+
+ tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}}
+
+ tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}}
+
+ tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}}
+}
+
+namespace ExpandingFunctionParameters {
+ template<typename ...T>
+ struct X0 {
+ typedef int type;
+ };
+
+ template<typename ...T>
+ struct X1 {
+ template<typename ... U>
+ typename X0<T(T, U...)...>::type f(U...);
+ };
+
+ void test() {
+ X1<float> x1;
+ x1.f(17, 3.14159);
+ }
+}
+
+namespace PR10230 {
+ template<typename>
+ struct s
+ {
+ template<typename... Args>
+ auto f() -> int(&)[sizeof...(Args)];
+ };
+
+ void main()
+ {
+ int (&ir1)[1] = s<int>().f<int>();
+ int (&ir3)[3] = s<int>().f<int, float, double>();
+ }
+}