// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s // C++1z [temp.local]p1: // Like normal (non-template) classes, class templates have an // injected-class-name (Clause 9). The injected-class-name can // be used as a template-name or a type-name. template char id; template struct TempType {}; template class> struct TempTemp {}; template void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}} template class> void use(float&); // expected-note 2{{no known conversion}} template void use(char&); // expected-note 2{{invalid explicitly-specified argument}} template struct A { template struct C {}; struct B : C { // When it is used with a template-argument-list, A *aint; typename B::template C *cint; // as a template-argument for a template template-parameter, TempTemp a_as_temp; TempTemp c_as_temp; // or as the final identifier in the elaborated-type-specifier of a friend // class template declaration, template friend struct A; // it refers to the class template itself. // Otherwise, it is equivalent to the template-name followed by the // template-parameters of the class template enclosed in <>. A *aT; typename B::C *cT; TempType a_as_type; TempType c_as_type; friend struct A; friend struct B::C; void f(T &t) { use(t); // expected-error {{no matching function}} if constexpr (&id != &id) use(t); // expected-error {{no matching function}} } }; }; template struct A; template struct A; template struct A; // expected-note {{instantiation of}} template struct X0 { X0(); ~X0(); X0 f(const X0&); }; // Test non-type template parameters. template struct X1 { X1(); ~X1(); X1 f(const X1& x1a) { X1 x1b(x1a); return x1b; } }; // When it is used with a template-argument-list, it refers to the specified // class template specialization, which could be the current specialization // or another specialization. // FIXME: Test this clause. int i = 42; void test() { X0 x0; (void)x0; X1<42, i, &i> x1; (void)x1; }