jeudi 1 janvier 2015

Is the name of a non-static-member dependent when used within a non-static member function?

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