Both gcc 5.0 and clang 3.6 require the typename
keyword in the following example:
template<int n>
struct I
{
typedef int Type;
};
template<typename T>
struct A
{
int m;
void f()
{
typedef typename I<sizeof m>::Type Type; // typename required
}
};
This is covered by the following wording in the C++11 standard:
[temp.dep.type]/8
A type is dependent if it is
- 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
So I<sizeof m>
is dependent if sizeof m
is value-dependent.
[temp.dep.expr]/4
Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
sizeof unary-expression
[temp.dep.constexpr]/2
Expressions of the following form are value-dependent if the unary-expression or expression is typedependent or the type-id is dependent:
sizeof unary-expression
So sizeof m
is only dependent if m
is dependent.
[expr.prim.general]/8
Within the definition of a non-static member function, an identifier that names a non-static member is transformed to a class member access expression
So m
is the member in a class member access expression.
[temp.dep.type]/4
A name is a member of the current instantiation if it is
- An id-expression denoting the member in a class member access expression (5.2.5) for which the type of the object expression is the current instantiation, and the id-expression, when looked up (3.4.5), refers to at least one member of the current instantiation or a non-dependent base class thereof.
So it seems that m
is a member of the current instantiation.
[temp.dep.type]/5
A name is a member of an unknown specialization if it is
An id-expression denoting the member in a class member access expression (5.2.5) in which either
the type of the object expression is the current instantiation, the current instantiation has at least one dependent base class, and name lookup of the id-expression does not find a member of the current instantiation or a non-dependent base class thereof; or
the type of the object expression is dependent and is not the current instantiation.
So m
is NOT a member of an unknown specialization - it would be found by name lookup to be a member of the current instantiation.
[temp.dep.expr]/3
An id-expression is type-dependent if it contains
- an identifier associated by name lookup with one or more declarations declared with a dependent type,
- a nested-name-specifier or a qualified-id that names a member of an unknown specialization
Since m
is of type int
and is not a member of an unknown specialization, neither of these bullets would make the id-expression m
dependent.
[temp.dep.expr]/5
A class member access expression (5.2.5) is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization.
When m
is transformed to a class member access expression, it is still not dependent because it does not refer to a member of an unknown specialization.
Should m
be treated as dependent? On a related note, should this->m
be treated as dependent? What about std::declval<A>().m
?
EDIT
And finally, should &A::m
be dependent?
Aucun commentaire:
Enregistrer un commentaire