According to [expr.prim.id.qual] p3:
> The _nested-name-specifier_ `::` nominates the global namespace. A
_nested-name-specifier_ with a _computed-type-specifier_ nominates the
type denoted by the _computed-type-specifier_, which shall be a class or
enumeration type. **If a _nested-name-specifier_ `N` is declarative and
has a _simple-template-id_ with a template argument list `A` that
involves a template parameter, let `T` be the template nominated by `N`
without `A`. `T` shall be a class template.**
Meaning, the out-of-line definition of `A::f` in the following example
is ill-formed:
```
template<typename T>
struct A
{
void f();
};
template<typename T>
using B = A<T>;
template<typename T>
void B<T>::f() { } // error: a declarative nested name specifier cannot name an alias template
```
This patch diagnoses such cases as an extension (in group `alias-template-in-declaration-name`).
30 lines
617 B
C++
30 lines
617 B
C++
// RUN: %clang_cc1 -verify %s
|
|
|
|
template<typename T>
|
|
struct A {
|
|
void f();
|
|
};
|
|
|
|
template<typename T>
|
|
using B = A<T>;
|
|
|
|
template<typename T>
|
|
void B<T>::f() { } // expected-warning {{a declarative nested name specifier cannot name an alias template}}
|
|
|
|
template<>
|
|
void B<int>::f() { } // ok, template argument list of simple-template-id doesn't involve template parameters
|
|
|
|
namespace N {
|
|
|
|
template<typename T>
|
|
struct D {
|
|
void f();
|
|
};
|
|
|
|
template<typename T>
|
|
using E = D<T>;
|
|
}
|
|
|
|
template<typename T>
|
|
void N::E<T>::f() { } // expected-warning {{a declarative nested name specifier cannot name an alias template}}
|