Current C++ compilers (latest gcc, clang) require the typename
keyword in the example below:
template<class T>
struct A
{
};
template<class T>
void f(T)
{
struct C
{
};
typedef typename A<C>::Type Type; // typename required
}
If typename
is omitted gcc (4.9, 5.0) reports the error:
need 'typename' before 'A<f(T)::C>::Type' because 'A<f(T)::C>' is a dependent scope
This example is otherwise well-formed according to my reading of the C++11 standard.
This behaviour seems to be covered by the following wording:
[temp.dep.type]/8
A type is dependent if it is
a template parameter,
a member of an unknown specialization,
a nested class or enumeration that is a member of the current instantiation,
a cv-qualified type where the cv-unqualified type is dependent,
a compound type constructed from any dependent type,
an array type constructed from any dependent type or whose size is specified by a constant expression that is value-dependent,
a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent, or
denoted by decltype(expression), where expression is type-dependent.
However, according to [class.local] the class C
is a local class rather than a nested class. If so, why should A<C>
be treated as dependent?
EDIT
For bonus points, if the example is modified by adding a member enum to C
as follows:
template<typename T>
struct A
{
typedef T Type;
};
template<class T>
void f(T)
{
struct C
{
enum { value = T::value };
};
typedef typename A<C>::Type Type; // typename required
}
Should A<C>
now be treated as dependent?
According to my understanding (and the current wording of the standard), C
in your example is not dependent. Neither is A<C>::Type
, so the typename
is not required.
There is a fundamental difference between nested classes of class templates and local classes in function templates: The latter cannot be specialized, thus any reference to a local class inside a function template is uniform. That is, in every specialization of f
, C
refers to the class C
that is defined in this function template f
. That is not the case with class templates as you can indeed explicitly specialize members on their own (as covered in [temp.expl.spec]
/(1.6)):
template <typename T>
class A { class C{}; };
template <>
class A<int>::C { int i; };
However:
A type is dependent if it is
- a compound type constructed from any dependent type,
So if the definition was done as in dyp's example, C
would be dependent as it is constructed from T
.
There are unclarities in the standards wording that are being discussed in the comment section, e.g. about definitions of member functions that depend on T
and how that transposes to the classes dependency.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With