Richard Smith | cc92866 | 2014-10-17 20:37:29 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++11 -verify %s |
| 2 | |
| 3 | template<typename ...T> struct X { |
| 4 | void f(int); |
| 5 | void f(...); |
| 6 | static int n; |
| 7 | }; |
| 8 | |
| 9 | template<typename T, typename U> using A = T; |
| 10 | |
| 11 | // These definitions are OK, X<A<T, decltype(...)>...> is equivalent to X<T...> |
| 12 | // so this defines the member of the primary template. |
| 13 | template<typename ...T> |
| 14 | void X<A<T, decltype(f(T()))>...>::f(int) {} // expected-error {{undeclared}} |
| 15 | |
| 16 | template<typename ...T> |
| 17 | int X<A<T, decltype(f(T()))>...>::n = 0; // expected-error {{undeclared}} |
| 18 | |
| 19 | struct Y {}; void f(Y); |
| 20 | |
| 21 | void g() { |
| 22 | // OK, substitution succeeds. |
| 23 | X<Y>().f(0); |
| 24 | X<Y>::n = 1; |
| 25 | |
| 26 | // Error, substitution fails; this should not be treated as a SFINAE-able |
| 27 | // condition, so we don't select X<void>::f(...). |
| 28 | X<void>().f(0); // expected-note {{instantiation of}} |
| 29 | X<void>::n = 1; // expected-note {{instantiation of}} |
| 30 | } |