1 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 2 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z 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]; 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); } 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 } 102 103 // PR7463 104 namespace PR7463 { 105 const int f (); 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 } 109 110 namespace test0 { 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'}} 112 char *char_maker(); 113 void test() { 114 make(char_maker); // expected-error {{no matching function for call to 'make'}} 115 } 116 } 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 } 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 } 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 } 154 155 namespace test4 { 156 157 template <class> struct a { using b = const float; }; 158 template <class c> using d = typename a<c>::b; 159 160 template <class c> void e(d<c> *, c) {} 161 template void e(const float *, int); 162 163 } // namespace test4 164 165 // Verify that we can deduce enum-typed arguments correctly. 166 namespace test14 { 167 enum E { E0, E1 }; 168 template <E> struct A {}; 169 template <E e> void foo(const A<e> &a) {} 170 171 void test() { 172 A<E0> a; 173 foo(a); 174 } 175 } 176 177 namespace PR21536 { 178 template<typename ...T> struct X; 179 template<typename A, typename ...B> struct S { 180 static_assert(sizeof...(B) == 1, ""); 181 void f() { 182 using T = A; 183 using T = int; 184 185 using U = X<B...>; 186 using U = X<int>; 187 } 188 }; 189 template<typename ...T> void f(S<T...>); 190 void g() { f(S<int, int>()); } 191 } 192 193 namespace PR19372 { 194 template <template<typename...> class C, typename ...Us> struct BindBack { 195 template <typename ...Ts> using apply = C<Ts..., Us...>; 196 }; 197 template <typename, typename...> struct Y; 198 template <typename ...Ts> using Z = Y<Ts...>; 199 200 using T = BindBack<Z, int>::apply<>; 201 using T = Z<int>; 202 203 using U = BindBack<Z, int, int>::apply<char>; 204 using U = Z<char, int, int>; 205 206 namespace BetterReduction { 207 template<typename ...> struct S; 208 template<typename ...A> using X = S<A...>; // expected-note {{parameter}} 209 template<typename ...A> using Y = X<A..., A...>; 210 template<typename ...A> using Z = X<A..., 1, 2, 3>; // expected-error {{must be a type}} 211 212 using T = Y<int>; 213 using T = S<int, int>; 214 } 215 } 216 217 namespace PR18645 { 218 template<typename F> F Quux(F &&f); 219 auto Baz = Quux(Quux<float>); 220 } 221 222 namespace NonDeducedNestedNameSpecifier { 223 template<typename T> struct A { 224 template<typename U> struct B { 225 B(int) {} 226 }; 227 }; 228 229 template<typename T> int f(A<T>, typename A<T>::template B<T>); 230 int k = f(A<int>(), 0); 231 } 232 233 namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity { 234 namespace ns1 { 235 236 template<class...> struct B { }; 237 template<class H, class ... Ts> struct B<H, Ts...> : B<> { }; 238 template<class ... Ts> struct D : B<Ts...> { }; 239 240 template<class T, class ... Ts> void f(B<T, Ts...> &) { } 241 242 int main() { 243 D<int, char> d; 244 f<int>(d); 245 } 246 } //end ns1 247 248 namespace ns2 { 249 250 template <int i, typename... Es> struct tup_impl; 251 252 template <int i> struct tup_impl<i> {}; // empty tail 253 254 template <int i, typename Head, typename... Tail> 255 struct tup_impl<i, Head, Tail...> : tup_impl<i + 1, Tail...> { 256 using value_type = Head; 257 Head head; 258 }; 259 260 template <typename... Es> struct tup : tup_impl<0, Es...> {}; 261 262 template <typename Head, int i, typename... Tail> 263 Head &get_helper(tup_impl<i, Head, Tail...> &t) { 264 return t.head; 265 } 266 267 template <typename Head, int i, typename... Tail> 268 Head const &get_helper(tup_impl<i, Head, Tail...> const &t) { 269 return t.head; 270 } 271 272 int main() { 273 tup<int, double, char> t; 274 get_helper<double>(t); 275 return 0; 276 } 277 } // end ns2 278 } 279 280 namespace multiple_deduction_different_type { 281 template<typename T, T v> struct X {}; 282 template<template<typename T, T> class X, typename T, typename U, int N> 283 void f(X<T, N>, X<U, N>) {} // expected-note 2{{values of conflicting types}} 284 template<template<typename T, T> class X, typename T, typename U, const int *N> 285 void g(X<T, N>, X<U, N>) {} // expected-note 0-2{{values of conflicting types}} 286 int n; 287 void h() { 288 f(X<int, 1+1>(), X<unsigned int, 3-1>()); // expected-error {{no matching function}} 289 f(X<unsigned int, 1+1>(), X<int, 3-1>()); // expected-error {{no matching function}} 290 #if __cplusplus > 201402L 291 g(X<const int*, &n>(), X<int*, &n + 1 - 1>()); // expected-error {{no matching function}} 292 g(X<int*, &n>(), X<const int*, &n + 1 - 1>()); // expected-error {{no matching function}} 293 #endif 294 } 295 296 template<template<typename T, T> class X, typename T, typename U, T N> 297 void x(X<T, N>, int(*)[N], X<U, N>) {} // expected-note 1+{{candidate}} 298 template<template<typename T, T> class X, typename T, typename U, T N> 299 void x(int(*)[N], X<T, N>, X<U, N>) {} // expected-note 1+{{candidate}} 300 int arr[3]; 301 void y() { 302 x(X<int, 3>(), &arr, X<int, 3>()); 303 x(&arr, X<int, 3>(), X<int, 3>()); 304 305 x(X<int, 3>(), &arr, X<char, 3>()); // expected-error {{no matching function}} 306 x(&arr, X<int, 3>(), X<char, 3>()); // expected-error {{no matching function}} 307 308 x(X<char, 3>(), &arr, X<char, 3>()); 309 x(&arr, X<char, 3>(), X<char, 3>()); 310 } 311 } 312 313 namespace nullptr_deduction { 314 using nullptr_t = decltype(nullptr); 315 316 template<typename T, T v> struct X {}; 317 template<typename T, T v> void f(X<T, v>) { 318 static_assert(!v, ""); // expected-warning 2{{implicit conversion of nullptr constant to 'bool'}} 319 } 320 void g() { 321 f(X<int*, nullptr>()); // expected-note {{instantiation of}} 322 f(X<nullptr_t, nullptr>()); // expected-note {{instantiation of}} 323 } 324 325 template<template<typename T, T> class X, typename T, int *P> 326 void f0(X<T, P>) {} // expected-note {{deduced non-type template argument does not have the same type as the corresponding template parameter ('std::nullptr_t' vs 'int *')}} 327 void h0() { 328 f0(X<int*, nullptr>()); 329 f0(X<nullptr_t, nullptr>()); // expected-error {{no matching function}} 330 } 331 332 template<template<typename T, T> class X, typename T, typename U, int *P> 333 void f1(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}} 334 void h() { 335 f1(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}} 336 f1(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}} 337 } 338 339 template<template<typename T, T> class X, typename T, typename U, nullptr_t P> 340 void f2(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}} 341 void i() { 342 f2(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}} 343 f2(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}} 344 } 345 } 346 347 namespace member_pointer { 348 struct A { void f(int); }; 349 template<typename T, void (A::*F)(T)> struct B; 350 template<typename T> struct C; 351 template<typename T, void (A::*F)(T)> struct C<B<T, F>> { 352 C() { A a; T t; (a.*F)(t); } 353 }; 354 C<B<int, &A::f>> c; 355 } 356 357 namespace deduction_substitution_failure { 358 template<typename T> struct Fail { typedef typename T::error error; }; // expected-error 2{{prior to '::'}} 359 360 template<typename T, typename U> struct A {}; 361 template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}} 362 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>'}} 363 364 template<typename T, typename U> int B; // expected-warning 0-1 {{extension}} 365 template<typename T> int B<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}} 366 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]}} 367 } 368 369 namespace deduction_after_explicit_pack { 370 template<typename ...T, typename U> int *f(T ...t, int &r, U *u) { 371 return u; 372 } 373 template<typename U, typename ...T> int *g(T ...t, int &r, U *u) { 374 return u; 375 } 376 void h(float a, double b, int c) { 377 f<float&, double&>(a, b, c, &c); // ok 378 g<int, float&, double&>(a, b, c, &c); // ok 379 } 380 381 template<class... ExtraArgs> 382 int test(ExtraArgs..., unsigned vla_size, const char *input); 383 int n = test(0, ""); 384 385 template <typename... T> void i(T..., int, T..., ...); // expected-note 5{{deduced packs of different lengths}} 386 void j() { 387 i(0); 388 i(0, 1); // expected-error {{no match}} 389 i(0, 1, 2); // expected-error {{no match}} 390 i<>(0); 391 i<>(0, 1); // expected-error {{no match}} 392 i<>(0, 1, 2); // expected-error {{no match}} 393 i<int, int>(0, 1, 2, 3, 4); 394 i<int, int>(0, 1, 2, 3, 4, 5); // expected-error {{no match}} 395 } 396 397 // GCC alarmingly accepts this by deducing T={int} by matching the second 398 // parameter against the first argument, then passing the first argument 399 // through the first parameter. 400 template<typename... T> struct X { X(int); operator int(); }; 401 template<typename... T> void p(T..., X<T...>, ...); // expected-note {{deduced packs of different lengths for parameter 'T' (<> vs. <int>)}} 402 void q() { p(X<int>(0), 0); } // expected-error {{no match}} 403 404 struct A { 405 template <typename T> void f(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} 406 void f(); // expected-note 2{{requires 0}} 407 408 template <typename T> static void g(T, void *, int = 0); // expected-note 2{{no known conversion from 'double' to 'void *' for 2nd argument}} 409 void g(); // expected-note 2{{requires 0}} 410 411 void h() { 412 f(1.0, 2.0); // expected-error {{no match}} 413 g(1.0, 2.0); // expected-error {{no match}} 414 } 415 }; 416 void f(A a) { 417 a.f(1.0, 2.0); // expected-error {{no match}} 418 a.g(1.0, 2.0); // expected-error {{no match}} 419 } 420 } 421 422 namespace overload_vs_pack { 423 void f(int); 424 void f(float); 425 void g(double); 426 427 template<typename ...T> struct X {}; 428 template<typename ...T> void x(T...); 429 430 template<typename ...T> struct Y { typedef int type(typename T::error...); }; 431 template<> struct Y<int, float, double> { typedef int type; }; 432 433 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>)}} 434 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>)}} 435 436 template<typename T> int &h1(decltype(g1(X<int, float, T>(), f, f, g)) *p); 437 template<typename T> float &h1(...); 438 439 template<typename T> int &h2(decltype(g2(x<int, float, T>, f, f, g)) *p); 440 template<typename T> float &h2(...); 441 442 int n1 = g1(X<int, float>(), f, g); // expected-error {{no matching function}} 443 int n2 = g2(x<int, float>, f, g); // expected-error {{no matching function}} 444 445 int &a1 = h1<double>(0); // ok, skip deduction for 'f's, deduce matching value from 'g' 446 int &a2 = h2<double>(0); 447 448 float &b1 = h1<float>(0); // deduce mismatching value from 'g', so we do not trigger instantiation of Y 449 float &b2 = h2<float>(0); 450 451 template<typename ...T> int partial_deduction(void (*...f)(T)); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}} 452 int pd1 = partial_deduction(f, g); // expected-error {{no matching function}} 453 454 template<typename ...T> int partial_deduction_2(void (*...f)(T), ...); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}} 455 int pd2 = partial_deduction_2(f, g); // expected-error {{no matching function}} 456 457 namespace cwg_example { 458 void f(char, char); 459 void f(int, int); 460 void x(int, char); 461 462 template<typename T, typename ...U> void j(void(*)(U...), void (*...fns)(T, U)); 463 void test() { j(x, f, x); } 464 } 465 } 466 467 namespace b29946541 { 468 template<typename> class A {}; 469 template<typename T, typename U, template<typename, typename> class C> 470 void f(C<T, U>); // expected-note {{failed template argument deduction}} 471 void g(A<int> a) { f(a); } // expected-error {{no match}} 472 } 473 474 namespace deduction_from_empty_list { 475 template<int M, int N = 5> void f(int (&&)[N], int (&&)[N]) { // expected-note {{1 vs. 2}} 476 static_assert(M == N, ""); 477 } 478 479 void test() { 480 f<5>({}, {}); 481 f<1>({}, {0}); 482 f<1>({0}, {}); 483 f<1>({0}, {0}); 484 f<1>({0}, {0, 1}); // expected-error {{no matching}} 485 } 486 } 487 488 namespace check_extended_pack { 489 template<typename T> struct X { typedef int type; }; 490 template<typename ...T> void f(typename X<T>::type...); 491 template<typename T> void f(T, int, int); 492 void g() { 493 f<int>(0, 0, 0); 494 } 495 496 template<int, int*> struct Y {}; 497 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')}} 498 int n; 499 void h() { g<0>(Y<0, &n>()); } // expected-error {{no matching function}} 500 } 501 502 namespace dependent_template_template_param_non_type_param_type { 503 template<int N> struct A { 504 template<typename V = int, V M = 12, V (*Y)[M], template<V (*v)[M]> class W> 505 A(W<Y>); 506 }; 507 508 int n[12]; 509 template<int (*)[12]> struct Q {}; 510 Q<&n> qn; 511 A<0> a(qn); 512 } 513 514 namespace dependent_list_deduction { 515 template<typename T, T V> void a(const int (&)[V]) { 516 static_assert(is_same<T, decltype(sizeof(0))>::value, ""); 517 static_assert(V == 3, ""); 518 } 519 template<typename T, T V> void b(const T (&)[V]) { 520 static_assert(is_same<T, int>::value, ""); 521 static_assert(V == 3, ""); 522 } 523 template<typename T, T V> void c(const T (&)[V]) { 524 static_assert(is_same<T, decltype(sizeof(0))>::value, ""); 525 static_assert(V == 3, ""); 526 } 527 void d() { 528 a({1, 2, 3}); 529 #if __cplusplus <= 201402L 530 // expected-error@-2 {{no match}} expected-note@-15 {{couldn't infer template argument 'T'}} 531 #endif 532 b({1, 2, 3}); 533 c({{}, {}, {}}); 534 #if __cplusplus <= 201402L 535 // expected-error@-2 {{no match}} expected-note@-12 {{couldn't infer template argument 'T'}} 536 #endif 537 } 538 539 template<typename ...T> struct X; 540 template<int ...T> struct Y; 541 template<typename ...T, T ...V> void f(const T (&...p)[V]) { 542 static_assert(is_same<X<T...>, X<int, char, char>>::value, ""); 543 static_assert(is_same<Y<V...>, Y<3, 2, 4>>::value, ""); 544 } 545 template<typename ...T, T ...V> void g(const T (&...p)[V]) { 546 static_assert(is_same<X<T...>, X<int, decltype(sizeof(0))>>::value, ""); 547 static_assert(is_same<Y<V...>, Y<2, 3>>::value, ""); 548 } 549 void h() { 550 f({1, 2, 3}, {'a', 'b'}, "foo"); 551 g({1, 2}, {{}, {}, {}}); 552 #if __cplusplus <= 201402 553 // expected-error@-2 {{no match}} 554 // expected-note@-9 {{deduced incomplete pack}} 555 // We deduce V$1 = (size_t)3, which in C++1z also deduces T$1 = size_t. 556 #endif 557 } 558 } 559 560 namespace designators { 561 template<typename T, int N> constexpr int f(T (&&)[N]) { return N; } // expected-note 2{{couldn't infer template argument 'T'}} 562 static_assert(f({1, 2, [20] = 3}) == 3, ""); // expected-error {{no matching function}} expected-warning 2{{C99}} expected-note {{}} 563 564 static_assert(f({.a = 1, .b = 2}) == 3, ""); // expected-error {{no matching function}} 565 } 566 567 namespace nested_packs { 568 template<typename ...T, typename ...U> void f(T (*...f)(U...)); // expected-note {{deduced packs of different lengths for parameter 'U' (<> vs. <int>)}} 569 void g() { f(g); f(g, g); f(g, g, g); } 570 void h(int) { f(h); f(h, h); f(h, h, h); } 571 void i() { f(g, h); } // expected-error {{no matching function}} 572 573 #if __cplusplus >= 201703L 574 template<auto ...A> struct Q {}; 575 template<typename ...T, T ...A, T ...B> void q(Q<A...>, Q<B...>); // #q 576 void qt(Q<> q0, Q<1, 2> qii, Q<1, 2, 3> qiii) { 577 q(q0, q0); 578 q(qii, qii); 579 q(qii, qiii); // expected-error {{no match}} expected-note@#q {{deduced packs of different lengths for parameter 'T' (<int, int> vs. <int, int, int>)}} 580 q(q0, qiii); // expected-error {{no match}} expected-note@#q {{deduced packs of different lengths for parameter 'T' (<> vs. <int, int, int>)}} 581 } 582 #endif 583 } 584 585 namespace PR44890 { 586 template<typename ...Ts> 587 struct tuple {}; 588 589 template<int I, typename ...Ts> 590 int get0(const tuple<Ts...> &t) { return 0; } 591 592 template<typename ...Ts> struct tuple_wrapper : tuple<Ts...> { 593 template<int I> int get() { return get0<0, Ts...>(*this); } 594 }; 595 596 int f() { 597 tuple_wrapper<int> w; 598 return w.get<0>(); 599 } 600 } 601 602 namespace merge_size_only_deductions { 603 #if __cplusplus >= 201703L 604 // Based on a testcase by Hubert Tong. 605 template<typename ...> struct X {}; 606 template<auto ...> struct Y {}; 607 template<typename T> struct id { using Type = T; }; 608 609 template<typename ...T, typename T::Type ...V> 610 int f(X<char [V] ...>, Y<V ...>, X<T ...>); 611 612 using size_t = __SIZE_TYPE__; 613 int a = f(X<char [1], char [2]>(), Y<(size_t)1, (size_t)2>(), X<id<size_t>, id<size_t>>()); 614 int b = f(X<char [1], char [2]>(), Y<1, 2>(), X<id<int>, id<int>>()); 615 #endif 616 } 617 618 namespace PR49724 { 619 struct A; 620 template<int A::*> class X {}; 621 template<int A::*P> void f(X<P>); 622 void g(X<nullptr> x) { f(x); } 623 624 template<void (A::*)()> class Y {}; 625 template<void (A::*P)()> void f(Y<P>); 626 void g(Y<nullptr> y) { f(y); } 627 } 628