Richard Smith | d8a52a7 | 2014-11-12 01:43:45 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 |
Richard Smith | 593d6a1 | 2016-12-23 01:30:39 +0000 | [diff] [blame] | 2 | // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z |
Douglas Gregor | adee3e3 | 2009-11-11 23:06:43 +0000 | [diff] [blame] | 3 | |
| 4 | // Template argument deduction with template template parameters. |
| 5 | template<typename T, template<T> class A> |
| 6 | struct X0 { |
| 7 | static const unsigned value = 0; |
| 8 | }; |
| 9 | |
| 10 | template<template<int> class A> |
| 11 | struct X0<int, A> { |
| 12 | static const unsigned value = 1; |
| 13 | }; |
| 14 | |
| 15 | template<int> struct X0i; |
| 16 | template<long> struct X0l; |
| 17 | int array_x0a[X0<long, X0l>::value == 0? 1 : -1]; |
| 18 | int array_x0b[X0<int, X0i>::value == 1? 1 : -1]; |
| 19 | |
| 20 | template<typename T, typename U> |
| 21 | struct is_same { |
| 22 | static const bool value = false; |
| 23 | }; |
| 24 | |
| 25 | template<typename T> |
| 26 | struct is_same<T, T> { |
| 27 | static const bool value = true; |
| 28 | }; |
| 29 | |
| 30 | template<typename T> struct allocator { }; |
| 31 | template<typename T, typename Alloc = allocator<T> > struct vector {}; |
| 32 | |
| 33 | // Fun with meta-lambdas! |
| 34 | struct _1 {}; |
| 35 | struct _2 {}; |
| 36 | |
| 37 | // Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T. |
| 38 | template<typename T, typename Arg1, typename Arg2> |
| 39 | struct Replace { |
| 40 | typedef T type; |
| 41 | }; |
| 42 | |
| 43 | // Replacement of the whole type. |
| 44 | template<typename Arg1, typename Arg2> |
| 45 | struct Replace<_1, Arg1, Arg2> { |
| 46 | typedef Arg1 type; |
| 47 | }; |
| 48 | |
| 49 | template<typename Arg1, typename Arg2> |
| 50 | struct Replace<_2, Arg1, Arg2> { |
| 51 | typedef Arg2 type; |
| 52 | }; |
| 53 | |
| 54 | // Replacement through cv-qualifiers |
| 55 | template<typename T, typename Arg1, typename Arg2> |
| 56 | struct Replace<const T, Arg1, Arg2> { |
| 57 | typedef typename Replace<T, Arg1, Arg2>::type const type; |
| 58 | }; |
| 59 | |
| 60 | // Replacement of templates |
| 61 | template<template<typename> class TT, typename T1, typename Arg1, typename Arg2> |
| 62 | struct Replace<TT<T1>, Arg1, Arg2> { |
| 63 | typedef TT<typename Replace<T1, Arg1, Arg2>::type> type; |
| 64 | }; |
| 65 | |
| 66 | template<template<typename, typename> class TT, typename T1, typename T2, |
| 67 | typename Arg1, typename Arg2> |
| 68 | struct Replace<TT<T1, T2>, Arg1, Arg2> { |
| 69 | typedef TT<typename Replace<T1, Arg1, Arg2>::type, |
| 70 | typename Replace<T2, Arg1, Arg2>::type> type; |
| 71 | }; |
| 72 | |
| 73 | // Just for kicks... |
| 74 | template<template<typename, typename> class TT, typename T1, |
| 75 | typename Arg1, typename Arg2> |
| 76 | struct Replace<TT<T1, _2>, Arg1, Arg2> { |
| 77 | typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type; |
| 78 | }; |
| 79 | |
| 80 | int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1]; |
| 81 | int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1]; |
| 82 | int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1]; |
| 83 | int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1]; |
| 84 | 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] | 85 | |
| 86 | // PR5911 |
| 87 | template <typename T, int N> void f(const T (&a)[N]); |
| 88 | int iarr[] = { 1 }; |
| 89 | void test_PR5911() { f(iarr); } |
Chandler Carruth | c126311 | 2010-02-07 21:33:28 +0000 | [diff] [blame] | 90 | |
| 91 | // Must not examine base classes of incomplete type during template argument |
| 92 | // deduction. |
| 93 | namespace PR6257 { |
| 94 | template <typename T> struct X { |
| 95 | template <typename U> X(const X<U>& u); |
| 96 | }; |
| 97 | struct A; |
| 98 | void f(A& a); |
| 99 | void f(const X<A>& a); |
| 100 | void test(A& a) { (void)f(a); } |
| 101 | } |
Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 102 | |
| 103 | // PR7463 |
| 104 | namespace PR7463 { |
Chandler Carruth | cb3b5a4 | 2010-07-14 06:36:18 +0000 | [diff] [blame] | 105 | const int f (); |
Douglas Gregor | 603d81b | 2010-07-13 08:18:22 +0000 | [diff] [blame] | 106 | template <typename T_> void g (T_&); // expected-note{{T_ = int}} |
| 107 | void h (void) { g(f()); } // expected-error{{no matching function for call}} |
| 108 | } |
John McCall | 42d7d19 | 2010-08-05 09:05:08 +0000 | [diff] [blame] | 109 | |
| 110 | namespace test0 { |
Davide Italiano | 32cbff7 | 2015-08-15 15:23:14 +0000 | [diff] [blame] | 111 | 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] | 112 | char *char_maker(); |
| 113 | void test() { |
| 114 | make(char_maker); // expected-error {{no matching function for call to 'make'}} |
| 115 | } |
| 116 | } |
John McCall | f733268 | 2010-08-19 00:20:19 +0000 | [diff] [blame] | 117 | |
| 118 | namespace test1 { |
| 119 | template<typename T> void foo(const T a[3][3]); |
| 120 | void test() { |
| 121 | int a[3][3]; |
| 122 | foo(a); |
| 123 | } |
| 124 | } |
John McCall | 0856906 | 2010-08-28 22:14:41 +0000 | [diff] [blame] | 125 | |
| 126 | // PR7708 |
| 127 | namespace test2 { |
| 128 | template<typename T> struct Const { typedef void const type; }; |
| 129 | |
| 130 | template<typename T> void f(T, typename Const<T>::type*); |
| 131 | template<typename T> void f(T, void const *); |
| 132 | |
| 133 | void test() { |
| 134 | void *p = 0; |
| 135 | f(0, p); |
| 136 | } |
| 137 | } |
John McCall | 036855a | 2010-10-12 19:40:14 +0000 | [diff] [blame] | 138 | |
| 139 | // rdar://problem/8537391 |
| 140 | namespace test3 { |
| 141 | struct Foo { |
| 142 | template <void F(char)> static inline void foo(); |
| 143 | }; |
| 144 | |
| 145 | class Bar { |
| 146 | template<typename T> static inline void wobble(T ch); |
| 147 | |
| 148 | public: |
| 149 | static void madness() { |
| 150 | Foo::foo<wobble<char> >(); |
| 151 | } |
| 152 | }; |
| 153 | } |
John McCall | 6730e4d | 2011-07-15 07:47:58 +0000 | [diff] [blame] | 154 | |
| 155 | // Verify that we can deduce enum-typed arguments correctly. |
| 156 | namespace test14 { |
| 157 | enum E { E0, E1 }; |
| 158 | template <E> struct A {}; |
| 159 | template <E e> void foo(const A<e> &a) {} |
| 160 | |
| 161 | void test() { |
| 162 | A<E0> a; |
| 163 | foo(a); |
| 164 | } |
| 165 | } |
Richard Smith | d8a52a7 | 2014-11-12 01:43:45 +0000 | [diff] [blame] | 166 | |
| 167 | namespace PR21536 { |
| 168 | template<typename ...T> struct X; |
| 169 | template<typename A, typename ...B> struct S { |
| 170 | static_assert(sizeof...(B) == 1, ""); |
| 171 | void f() { |
| 172 | using T = A; |
| 173 | using T = int; |
| 174 | |
| 175 | using U = X<B...>; |
| 176 | using U = X<int>; |
| 177 | } |
| 178 | }; |
| 179 | template<typename ...T> void f(S<T...>); |
| 180 | void g() { f(S<int, int>()); } |
| 181 | } |
Richard Smith | 96d71c3 | 2014-11-12 23:38:38 +0000 | [diff] [blame] | 182 | |
| 183 | namespace PR19372 { |
| 184 | template <template<typename...> class C, typename ...Us> struct BindBack { |
| 185 | template <typename ...Ts> using apply = C<Ts..., Us...>; |
| 186 | }; |
| 187 | template <typename, typename...> struct Y; |
| 188 | template <typename ...Ts> using Z = Y<Ts...>; |
| 189 | |
| 190 | using T = BindBack<Z, int>::apply<>; |
| 191 | using T = Z<int>; |
| 192 | |
| 193 | using U = BindBack<Z, int, int>::apply<char>; |
| 194 | using U = Z<char, int, int>; |
Richard Smith | 316c6dc | 2014-11-12 23:43:08 +0000 | [diff] [blame] | 195 | |
| 196 | namespace BetterReduction { |
| 197 | template<typename ...> struct S; |
Richard Smith | 5357c08 | 2014-11-12 23:50:13 +0000 | [diff] [blame] | 198 | template<typename ...A> using X = S<A...>; // expected-note {{parameter}} |
Richard Smith | 316c6dc | 2014-11-12 23:43:08 +0000 | [diff] [blame] | 199 | template<typename ...A> using Y = X<A..., A...>; |
Richard Smith | 5357c08 | 2014-11-12 23:50:13 +0000 | [diff] [blame] | 200 | 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] | 201 | |
| 202 | using T = Y<int>; |
| 203 | using T = S<int, int>; |
| 204 | } |
Richard Smith | 96d71c3 | 2014-11-12 23:38:38 +0000 | [diff] [blame] | 205 | } |
Nathan Sidwell | 9609002 | 2015-01-16 15:20:14 +0000 | [diff] [blame] | 206 | |
| 207 | namespace PR18645 { |
| 208 | template<typename F> F Quux(F &&f); |
| 209 | auto Baz = Quux(Quux<float>); |
| 210 | } |
Richard Smith | 50d5b97 | 2015-12-30 20:56:05 +0000 | [diff] [blame] | 211 | |
| 212 | namespace NonDeducedNestedNameSpecifier { |
| 213 | template<typename T> struct A { |
| 214 | template<typename U> struct B { |
| 215 | B(int) {} |
| 216 | }; |
| 217 | }; |
| 218 | |
| 219 | template<typename T> int f(A<T>, typename A<T>::template B<T>); |
| 220 | int k = f(A<int>(), 0); |
| 221 | } |
Faisal Vali | 683b074 | 2016-05-19 02:28:21 +0000 | [diff] [blame] | 222 | |
| 223 | namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity { |
| 224 | namespace ns1 { |
| 225 | |
| 226 | template<class...> struct B { }; |
| 227 | template<class H, class ... Ts> struct B<H, Ts...> : B<> { }; |
| 228 | template<class ... Ts> struct D : B<Ts...> { }; |
| 229 | |
| 230 | template<class T, class ... Ts> void f(B<T, Ts...> &) { } |
| 231 | |
| 232 | int main() { |
| 233 | D<int, char> d; |
| 234 | f<int>(d); |
| 235 | } |
| 236 | } //end ns1 |
| 237 | |
| 238 | namespace ns2 { |
| 239 | |
| 240 | template <int i, typename... Es> struct tup_impl; |
| 241 | |
| 242 | template <int i> struct tup_impl<i> {}; // empty tail |
| 243 | |
| 244 | template <int i, typename Head, typename... Tail> |
| 245 | struct tup_impl<i, Head, Tail...> : tup_impl<i + 1, Tail...> { |
| 246 | using value_type = Head; |
| 247 | Head head; |
| 248 | }; |
| 249 | |
| 250 | template <typename... Es> struct tup : tup_impl<0, Es...> {}; |
| 251 | |
| 252 | template <typename Head, int i, typename... Tail> |
| 253 | Head &get_helper(tup_impl<i, Head, Tail...> &t) { |
| 254 | return t.head; |
| 255 | } |
| 256 | |
| 257 | template <typename Head, int i, typename... Tail> |
| 258 | Head const &get_helper(tup_impl<i, Head, Tail...> const &t) { |
| 259 | return t.head; |
| 260 | } |
| 261 | |
| 262 | int main() { |
| 263 | tup<int, double, char> t; |
| 264 | get_helper<double>(t); |
| 265 | return 0; |
| 266 | } |
| 267 | } // end ns2 |
Richard Smith | 38175a2 | 2016-09-28 22:08:38 +0000 | [diff] [blame] | 268 | } |
| 269 | |
Richard Smith | 593d6a1 | 2016-12-23 01:30:39 +0000 | [diff] [blame] | 270 | namespace multiple_deduction_different_type { |
| 271 | template<typename T, T v> struct X {}; |
| 272 | template<template<typename T, T> class X, typename T, typename U, int N> |
| 273 | void f(X<T, N>, X<U, N>) {} // expected-note 2{{values of conflicting types}} |
| 274 | template<template<typename T, T> class X, typename T, typename U, const int *N> |
| 275 | void g(X<T, N>, X<U, N>) {} // expected-note 0-2{{values of conflicting types}} |
| 276 | int n; |
| 277 | void h() { |
| 278 | f(X<int, 1+1>(), X<unsigned int, 3-1>()); // expected-error {{no matching function}} |
| 279 | f(X<unsigned int, 1+1>(), X<int, 3-1>()); // expected-error {{no matching function}} |
| 280 | #if __cplusplus > 201402L |
| 281 | g(X<const int*, &n>(), X<int*, &n + 1 - 1>()); // expected-error {{no matching function}} |
| 282 | g(X<int*, &n>(), X<const int*, &n + 1 - 1>()); // expected-error {{no matching function}} |
| 283 | #endif |
| 284 | } |
| 285 | |
| 286 | template<template<typename T, T> class X, typename T, typename U, T N> |
| 287 | void x(X<T, N>, int(*)[N], X<U, N>) {} // expected-note 1+{{candidate}} |
| 288 | template<template<typename T, T> class X, typename T, typename U, T N> |
| 289 | void x(int(*)[N], X<T, N>, X<U, N>) {} // expected-note 1+{{candidate}} |
| 290 | int arr[3]; |
| 291 | void y() { |
| 292 | x(X<int, 3>(), &arr, X<int, 3>()); |
| 293 | x(&arr, X<int, 3>(), X<int, 3>()); |
| 294 | |
| 295 | x(X<int, 3>(), &arr, X<char, 3>()); // expected-error {{no matching function}} |
| 296 | x(&arr, X<int, 3>(), X<char, 3>()); // expected-error {{no matching function}} |
| 297 | |
| 298 | x(X<char, 3>(), &arr, X<char, 3>()); |
| 299 | x(&arr, X<char, 3>(), X<char, 3>()); |
| 300 | } |
| 301 | } |
| 302 | |
Richard Smith | 38175a2 | 2016-09-28 22:08:38 +0000 | [diff] [blame] | 303 | namespace nullptr_deduction { |
Richard Smith | 593d6a1 | 2016-12-23 01:30:39 +0000 | [diff] [blame] | 304 | using nullptr_t = decltype(nullptr); |
| 305 | |
Richard Smith | 38175a2 | 2016-09-28 22:08:38 +0000 | [diff] [blame] | 306 | template<typename T, T v> struct X {}; |
| 307 | template<typename T, T v> void f(X<T, v>) { |
| 308 | static_assert(!v, ""); |
| 309 | } |
Richard Smith | 593d6a1 | 2016-12-23 01:30:39 +0000 | [diff] [blame] | 310 | void g() { |
| 311 | f(X<int*, nullptr>()); |
| 312 | f(X<nullptr_t, nullptr>()); |
| 313 | } |
| 314 | |
| 315 | template<template<typename T, T> class X, typename T, typename U, int *P> |
| 316 | void f1(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}} |
| 317 | void h() { |
| 318 | f1(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}} |
| 319 | f1(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}} |
| 320 | } |
| 321 | |
| 322 | template<template<typename T, T> class X, typename T, typename U, nullptr_t P> |
| 323 | void f2(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}} |
| 324 | void i() { |
| 325 | f2(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}} |
| 326 | f2(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}} |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | namespace member_pointer { |
| 331 | struct A { void f(int); }; |
| 332 | template<typename T, void (A::*F)(T)> struct B; |
| 333 | template<typename T> struct C; |
| 334 | template<typename T, void (A::*F)(T)> struct C<B<T, F>> { |
| 335 | C() { A a; T t; (a.*F)(t); } |
| 336 | }; |
| 337 | C<B<int, &A::f>> c; |
Richard Smith | 38175a2 | 2016-09-28 22:08:38 +0000 | [diff] [blame] | 338 | } |
Richard Smith | 792c22d | 2016-12-24 04:09:05 +0000 | [diff] [blame] | 339 | |
| 340 | namespace deduction_substitution_failure { |
Richard Smith | e68a38f | 2016-12-24 04:20:31 +0000 | [diff] [blame] | 341 | template<typename T> struct Fail { typedef typename T::error error; }; // expected-error 2{{prior to '::'}} |
Richard Smith | 792c22d | 2016-12-24 04:09:05 +0000 | [diff] [blame] | 342 | |
| 343 | template<typename T, typename U> struct A {}; |
| 344 | template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}} |
Richard Smith | 32b4376 | 2017-01-08 22:45:21 +0000 | [diff] [blame] | 345 | A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}} expected-note {{in instantiation of template class 'deduction_substitution_failure::A<int, int>'}} |
Richard Smith | 792c22d | 2016-12-24 04:09:05 +0000 | [diff] [blame] | 346 | |
Richard Smith | 792c22d | 2016-12-24 04:09:05 +0000 | [diff] [blame] | 347 | template<typename T, typename U> int B; // expected-warning 0-1 {{extension}} |
Richard Smith | e68a38f | 2016-12-24 04:20:31 +0000 | [diff] [blame] | 348 | template<typename T> int B<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}} |
| 349 | int bi = B<char, char>; // expected-note {{during template argument deduction for variable template partial specialization 'B<T, typename Fail<T>::error>' [with T = char]}} |
Richard Smith | 792c22d | 2016-12-24 04:09:05 +0000 | [diff] [blame] | 350 | } |
Richard Smith | dadcc18 | 2017-01-02 23:00:32 +0000 | [diff] [blame] | 351 | |
| 352 | namespace deduction_after_explicit_pack { |
Richard Smith | de0d34a | 2017-01-09 07:14:40 +0000 | [diff] [blame] | 353 | template<typename ...T, typename U> int *f(T ...t, int &r, U *u) { |
Richard Smith | dadcc18 | 2017-01-02 23:00:32 +0000 | [diff] [blame] | 354 | return u; |
| 355 | } |
| 356 | template<typename U, typename ...T> int *g(T ...t, int &r, U *u) { |
| 357 | return u; |
| 358 | } |
| 359 | void h(float a, double b, int c) { |
Richard Smith | de0d34a | 2017-01-09 07:14:40 +0000 | [diff] [blame] | 360 | f<float&, double&>(a, b, c, &c); // ok |
Richard Smith | dadcc18 | 2017-01-02 23:00:32 +0000 | [diff] [blame] | 361 | g<int, float&, double&>(a, b, c, &c); // ok |
| 362 | } |
Richard Smith | de0d34a | 2017-01-09 07:14:40 +0000 | [diff] [blame] | 363 | |
Richard Smith | 6eedfe7 | 2017-01-09 08:01:21 +0000 | [diff] [blame] | 364 | template<class... ExtraArgs> |
| 365 | int test(ExtraArgs..., unsigned vla_size, const char *input); |
| 366 | int n = test(0, ""); |
| 367 | |
Richard Smith | de0d34a | 2017-01-09 07:14:40 +0000 | [diff] [blame] | 368 | template <typename... T> void i(T..., int, T..., ...); // expected-note 5{{deduced conflicting}} |
| 369 | void j() { |
| 370 | i(0); |
| 371 | i(0, 1); // expected-error {{no match}} |
| 372 | i(0, 1, 2); // expected-error {{no match}} |
| 373 | i<>(0); |
| 374 | i<>(0, 1); // expected-error {{no match}} |
| 375 | i<>(0, 1, 2); // expected-error {{no match}} |
| 376 | i<int, int>(0, 1, 2, 3, 4); |
| 377 | i<int, int>(0, 1, 2, 3, 4, 5); // expected-error {{no match}} |
| 378 | } |
| 379 | |
| 380 | // GCC alarmingly accepts this by deducing T={int} by matching the second |
| 381 | // parameter against the first argument, then passing the first argument |
| 382 | // through the first parameter. |
| 383 | template<typename... T> struct X { X(int); operator int(); }; |
| 384 | template<typename... T> void p(T..., X<T...>, ...); // expected-note {{deduced conflicting}} |
| 385 | void q() { p(X<int>(0), 0); } // expected-error {{no match}} |
Richard Smith | 14ead30 | 2017-01-10 20:19:21 +0000 | [diff] [blame] | 386 | |
| 387 | struct A { |
Richard Smith | 9d05e15 | 2017-01-10 20:52:50 +0000 | [diff] [blame^] | 388 | template <typename T> void f(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} |
| 389 | void f(); // expected-note 2{{requires 0}} |
| 390 | |
| 391 | template <typename T> static void g(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} |
| 392 | void g(); // expected-note 2{{requires 0}} |
| 393 | |
| 394 | void h() { |
| 395 | f(1.0, 2.0); // expected-error {{no match}} |
| 396 | g(1.0, 2.0); // expected-error {{no match}} |
| 397 | } |
Richard Smith | 14ead30 | 2017-01-10 20:19:21 +0000 | [diff] [blame] | 398 | }; |
Richard Smith | 9d05e15 | 2017-01-10 20:52:50 +0000 | [diff] [blame^] | 399 | void f(A a) { |
| 400 | a.f(1.0, 2.0); // expected-error {{no match}} |
| 401 | a.g(1.0, 2.0); // expected-error {{no match}} |
| 402 | } |
Richard Smith | dadcc18 | 2017-01-02 23:00:32 +0000 | [diff] [blame] | 403 | } |
Richard Smith | 539e8e3 | 2017-01-04 01:48:55 +0000 | [diff] [blame] | 404 | |
| 405 | namespace overload_vs_pack { |
| 406 | void f(int); |
| 407 | void f(float); |
| 408 | void g(double); |
| 409 | |
| 410 | template<typename ...T> struct X {}; |
| 411 | template<typename ...T> void x(T...); |
| 412 | |
| 413 | template<typename ...T> struct Y { typedef int type(typename T::error...); }; |
| 414 | template<> struct Y<int, float, double> { typedef int type; }; |
| 415 | |
| 416 | template<typename ...T> typename Y<T...>::type g1(X<T...>, void (*...fns)(T)); // expected-note {{deduced conflicting types for parameter 'T' (<int, float> vs. <(no value), double>)}} |
| 417 | template<typename ...T> typename Y<T...>::type g2(void(*)(T...), void (*...fns)(T)); // expected-note {{deduced conflicting types for parameter 'T' (<int, float> vs. <(no value), double>)}} |
| 418 | |
| 419 | template<typename T> int &h1(decltype(g1(X<int, float, T>(), f, f, g)) *p); |
| 420 | template<typename T> float &h1(...); |
| 421 | |
| 422 | template<typename T> int &h2(decltype(g2(x<int, float, T>, f, f, g)) *p); |
| 423 | template<typename T> float &h2(...); |
| 424 | |
| 425 | int n1 = g1(X<int, float>(), f, g); // expected-error {{no matching function}} |
| 426 | int n2 = g2(x<int, float>, f, g); // expected-error {{no matching function}} |
Richard Smith | 539e8e3 | 2017-01-04 01:48:55 +0000 | [diff] [blame] | 427 | |
| 428 | int &a1 = h1<double>(0); // ok, skip deduction for 'f's, deduce matching value from 'g' |
| 429 | int &a2 = h2<double>(0); |
| 430 | |
| 431 | float &b1 = h1<float>(0); // deduce mismatching value from 'g', so we do not trigger instantiation of Y |
| 432 | float &b2 = h2<float>(0); |
| 433 | |
| 434 | template<typename ...T> int partial_deduction(void (*...f)(T)); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}} |
| 435 | int pd1 = partial_deduction(f, g); // expected-error {{no matching function}} |
| 436 | |
| 437 | template<typename ...T> int partial_deduction_2(void (*...f)(T), ...); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}} |
| 438 | int pd2 = partial_deduction_2(f, g); // expected-error {{no matching function}} |
Richard Smith | 6298b44 | 2017-01-04 02:03:39 +0000 | [diff] [blame] | 439 | |
| 440 | namespace cwg_example { |
| 441 | void f(char, char); |
| 442 | void f(int, int); |
| 443 | void x(int, char); |
| 444 | |
| 445 | template<typename T, typename ...U> void j(void(*)(U...), void (*...fns)(T, U)); |
| 446 | void test() { j(x, f, x); } |
| 447 | } |
Richard Smith | 539e8e3 | 2017-01-04 01:48:55 +0000 | [diff] [blame] | 448 | } |
Richard Smith | ec7176e | 2017-01-05 02:31:32 +0000 | [diff] [blame] | 449 | |
| 450 | namespace b29946541 { |
| 451 | template<typename> class A {}; |
| 452 | template<typename T, typename U, template<typename, typename> class C> |
| 453 | void f(C<T, U>); // expected-note {{failed template argument deduction}} |
| 454 | void g(A<int> a) { f(a); } // expected-error {{no match}} |
| 455 | } |
Richard Smith | 9c5534c | 2017-01-05 04:16:30 +0000 | [diff] [blame] | 456 | |
| 457 | namespace deduction_from_empty_list { |
| 458 | template<int M, int N = 5> void f(int (&&)[N], int (&&)[N]) { // expected-note {{1 vs. 2}} |
| 459 | static_assert(M == N, ""); |
| 460 | } |
| 461 | |
| 462 | void test() { |
| 463 | f<5>({}, {}); |
| 464 | f<1>({}, {0}); |
| 465 | f<1>({0}, {}); |
| 466 | f<1>({0}, {0}); |
| 467 | f<1>({0}, {0, 1}); // expected-error {{no matching}} |
| 468 | } |
| 469 | } |
Richard Smith | 9c0c986 | 2017-01-05 20:27:28 +0000 | [diff] [blame] | 470 | |
| 471 | namespace check_extended_pack { |
| 472 | template<typename T> struct X { typedef int type; }; |
| 473 | template<typename ...T> void f(typename X<T>::type...); |
| 474 | template<typename T> void f(T, int, int); |
| 475 | void g() { |
| 476 | f<int>(0, 0, 0); |
| 477 | } |
| 478 | |
| 479 | template<int, int*> struct Y {}; |
| 480 | template<int ...N> void g(Y<N...>); // expected-note {{deduced non-type template argument does not have the same type as the corresponding template parameter ('int *' vs 'int')}} |
| 481 | int n; |
| 482 | void h() { g<0>(Y<0, &n>()); } // expected-error {{no matching function}} |
| 483 | } |