1 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 2 3 // Template argument deduction with template template parameters. 4 template<typename T, template<T> class A> 5 struct X0 { 6 static const unsigned value = 0; 7 }; 8 9 template<template<int> class A> 10 struct X0<int, A> { 11 static const unsigned value = 1; 12 }; 13 14 template<int> struct X0i; 15 template<long> struct X0l; 16 int array_x0a[X0<long, X0l>::value == 0? 1 : -1]; 17 int array_x0b[X0<int, X0i>::value == 1? 1 : -1]; 18 19 template<typename T, typename U> 20 struct is_same { 21 static const bool value = false; 22 }; 23 24 template<typename T> 25 struct is_same<T, T> { 26 static const bool value = true; 27 }; 28 29 template<typename T> struct allocator { }; 30 template<typename T, typename Alloc = allocator<T> > struct vector {}; 31 32 // Fun with meta-lambdas! 33 struct _1 {}; 34 struct _2 {}; 35 36 // Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T. 37 template<typename T, typename Arg1, typename Arg2> 38 struct Replace { 39 typedef T type; 40 }; 41 42 // Replacement of the whole type. 43 template<typename Arg1, typename Arg2> 44 struct Replace<_1, Arg1, Arg2> { 45 typedef Arg1 type; 46 }; 47 48 template<typename Arg1, typename Arg2> 49 struct Replace<_2, Arg1, Arg2> { 50 typedef Arg2 type; 51 }; 52 53 // Replacement through cv-qualifiers 54 template<typename T, typename Arg1, typename Arg2> 55 struct Replace<const T, Arg1, Arg2> { 56 typedef typename Replace<T, Arg1, Arg2>::type const type; 57 }; 58 59 // Replacement of templates 60 template<template<typename> class TT, typename T1, typename Arg1, typename Arg2> 61 struct Replace<TT<T1>, Arg1, Arg2> { 62 typedef TT<typename Replace<T1, Arg1, Arg2>::type> type; 63 }; 64 65 template<template<typename, typename> class TT, typename T1, typename T2, 66 typename Arg1, typename Arg2> 67 struct Replace<TT<T1, T2>, Arg1, Arg2> { 68 typedef TT<typename Replace<T1, Arg1, Arg2>::type, 69 typename Replace<T2, Arg1, Arg2>::type> type; 70 }; 71 72 // Just for kicks... 73 template<template<typename, typename> class TT, typename T1, 74 typename Arg1, typename Arg2> 75 struct Replace<TT<T1, _2>, Arg1, Arg2> { 76 typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type; 77 }; 78 79 int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1]; 80 int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1]; 81 int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1]; 82 int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1]; 83 int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, float> >::value? 1 : -1]; 84 85 // PR5911 86 template <typename T, int N> void f(const T (&a)[N]); 87 int iarr[] = { 1 }; 88 void test_PR5911() { f(iarr); } 89 90 // Must not examine base classes of incomplete type during template argument 91 // deduction. 92 namespace PR6257 { 93 template <typename T> struct X { 94 template <typename U> X(const X<U>& u); 95 }; 96 struct A; 97 void f(A& a); 98 void f(const X<A>& a); 99 void test(A& a) { (void)f(a); } 100 } 101 102 // PR7463 103 namespace PR7463 { 104 const int f (); 105 template <typename T_> void g (T_&); // expected-note{{T_ = int}} 106 void h (void) { g(f()); } // expected-error{{no matching function for call}} 107 } 108 109 namespace test0 { 110 template <class T> void make(const T *(*fn)()); // expected-note {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}} 111 char *char_maker(); 112 void test() { 113 make(char_maker); // expected-error {{no matching function for call to 'make'}} 114 } 115 } 116 117 namespace test1 { 118 template<typename T> void foo(const T a[3][3]); 119 void test() { 120 int a[3][3]; 121 foo(a); 122 } 123 } 124 125 // PR7708 126 namespace test2 { 127 template<typename T> struct Const { typedef void const type; }; 128 129 template<typename T> void f(T, typename Const<T>::type*); 130 template<typename T> void f(T, void const *); 131 132 void test() { 133 void *p = 0; 134 f(0, p); 135 } 136 } 137 138 // rdar://problem/8537391 139 namespace test3 { 140 struct Foo { 141 template <void F(char)> static inline void foo(); 142 }; 143 144 class Bar { 145 template<typename T> static inline void wobble(T ch); 146 147 public: 148 static void madness() { 149 Foo::foo<wobble<char> >(); 150 } 151 }; 152 } 153 154 // Verify that we can deduce enum-typed arguments correctly. 155 namespace test14 { 156 enum E { E0, E1 }; 157 template <E> struct A {}; 158 template <E e> void foo(const A<e> &a) {} 159 160 void test() { 161 A<E0> a; 162 foo(a); 163 } 164 } 165 166 namespace PR21536 { 167 template<typename ...T> struct X; 168 template<typename A, typename ...B> struct S { 169 static_assert(sizeof...(B) == 1, ""); 170 void f() { 171 using T = A; 172 using T = int; 173 174 using U = X<B...>; 175 using U = X<int>; 176 } 177 }; 178 template<typename ...T> void f(S<T...>); 179 void g() { f(S<int, int>()); } 180 } 181 182 namespace PR19372 { 183 template <template<typename...> class C, typename ...Us> struct BindBack { 184 template <typename ...Ts> using apply = C<Ts..., Us...>; 185 }; 186 template <typename, typename...> struct Y; 187 template <typename ...Ts> using Z = Y<Ts...>; 188 189 using T = BindBack<Z, int>::apply<>; 190 using T = Z<int>; 191 192 using U = BindBack<Z, int, int>::apply<char>; 193 using U = Z<char, int, int>; 194 195 namespace BetterReduction { 196 template<typename ...> struct S; 197 template<typename ...A> using X = S<A...>; // expected-note {{parameter}} 198 template<typename ...A> using Y = X<A..., A...>; 199 template<typename ...A> using Z = X<A..., 1, 2, 3>; // expected-error {{must be a type}} 200 201 using T = Y<int>; 202 using T = S<int, int>; 203 } 204 } 205 206 namespace PR18645 { 207 template<typename F> F Quux(F &&f); 208 auto Baz = Quux(Quux<float>); 209 } 210