Richard Smith | d8a52a7 | 2014-11-12 01:43:45 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 |
Douglas Gregor | adee3e3 | 2009-11-11 23:06:43 +0000 | [diff] [blame] | 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]; |
Chandler Carruth | c712ce1 | 2009-12-30 04:10:01 +0000 | [diff] [blame] | 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); } |
Chandler Carruth | c126311 | 2010-02-07 21:33:28 +0000 | [diff] [blame] | 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 | } |
Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 101 | |
| 102 | // PR7463 |
| 103 | namespace PR7463 { |
Chandler Carruth | cb3b5a4 | 2010-07-14 06:36:18 +0000 | [diff] [blame] | 104 | const int f (); |
Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 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 | } |
John McCall | 42d7d19 | 2010-08-05 09:05:08 +0000 | [diff] [blame] | 108 | |
| 109 | namespace test0 { |
Davide Italiano | 32cbff7 | 2015-08-15 15:23:14 +0000 | [diff] [blame] | 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'}} |
John McCall | 42d7d19 | 2010-08-05 09:05:08 +0000 | [diff] [blame] | 111 | char *char_maker(); |
| 112 | void test() { |
| 113 | make(char_maker); // expected-error {{no matching function for call to 'make'}} |
| 114 | } |
| 115 | } |
John McCall | f733268 | 2010-08-19 00:20:19 +0000 | [diff] [blame] | 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 | } |
John McCall | 0856906 | 2010-08-28 22:14:41 +0000 | [diff] [blame] | 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 | } |
John McCall | 036855a | 2010-10-12 19:40:14 +0000 | [diff] [blame] | 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 | } |
John McCall | 6730e4d | 2011-07-15 07:47:58 +0000 | [diff] [blame] | 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 | } |
Richard Smith | d8a52a7 | 2014-11-12 01:43:45 +0000 | [diff] [blame] | 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 | } |
Richard Smith | 96d71c3 | 2014-11-12 23:38:38 +0000 | [diff] [blame] | 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>; |
Richard Smith | 316c6dc | 2014-11-12 23:43:08 +0000 | [diff] [blame] | 194 | |
| 195 | namespace BetterReduction { |
| 196 | template<typename ...> struct S; |
Richard Smith | 5357c08 | 2014-11-12 23:50:13 +0000 | [diff] [blame] | 197 | template<typename ...A> using X = S<A...>; // expected-note {{parameter}} |
Richard Smith | 316c6dc | 2014-11-12 23:43:08 +0000 | [diff] [blame] | 198 | template<typename ...A> using Y = X<A..., A...>; |
Richard Smith | 5357c08 | 2014-11-12 23:50:13 +0000 | [diff] [blame] | 199 | template<typename ...A> using Z = X<A..., 1, 2, 3>; // expected-error {{must be a type}} |
Richard Smith | 316c6dc | 2014-11-12 23:43:08 +0000 | [diff] [blame] | 200 | |
| 201 | using T = Y<int>; |
| 202 | using T = S<int, int>; |
| 203 | } |
Richard Smith | 96d71c3 | 2014-11-12 23:38:38 +0000 | [diff] [blame] | 204 | } |
Nathan Sidwell | 9609002 | 2015-01-16 15:20:14 +0000 | [diff] [blame] | 205 | |
| 206 | namespace PR18645 { |
| 207 | template<typename F> F Quux(F &&f); |
| 208 | auto Baz = Quux(Quux<float>); |
| 209 | } |
Richard Smith | 50d5b97 | 2015-12-30 20:56:05 +0000 | [diff] [blame^] | 210 | |
| 211 | namespace NonDeducedNestedNameSpecifier { |
| 212 | template<typename T> struct A { |
| 213 | template<typename U> struct B { |
| 214 | B(int) {} |
| 215 | }; |
| 216 | }; |
| 217 | |
| 218 | template<typename T> int f(A<T>, typename A<T>::template B<T>); |
| 219 | int k = f(A<int>(), 0); |
| 220 | } |