Where does the C++98 standard specify when a call to a static member is dependent within a template?

若如初见. 提交于 2019-12-05 11:48:16

Dependent names are defined in 14.6.2. gcc complains about I<sizeof(f(0))> being dependent, let's figure that. 14.6.2.1 last bullet:

a 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 sizeof(f(0)) must be value-dependent. 14.6.2.3p2:

Expressions of the following form are value-dependent if the unary-expression is type-dependent ... sizeof unary-expression

so we're dependent if f(0) considered dependent. (Little experimenting shows gcc treats member any function dependent and free functions not dependent.) 14.6.2.2:

Except as described below, an expression is type-dependent if any subexpression is type-dependent.

And I don't see either type dependent subexpressions or anything relevant in the exception list.

The paragraph of the C++98 standard that covers this scenario is found in [temp.dep.expr]

An id-expression is type-dependent if it contains:

  • an identifier that was declared with a dependent type,

This wording is somewhat vague about identifiers that are overloaded and potentially declared with more than one type, as reported in DR 541 : http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html

This was resolved (in a more recent draft) by changing the paragraph to read:

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,

When considering the following code:

template<class T>
struct S
{
    static int f(int);
    static int f(int*);

    static T g(int*);
    static int g(int);

    static const int x = sizeof(f(0));
    static const int y = sizeof(g(0));
};

My interpretation is that the identifier f in the expression f(0) is not dependent, while the identifier g in the expression g(0) is dependent.

When determining if a function-call expression is dependent - though overload resolution is not performed - all overloads of the function are considered.

f is a member of S, which is a template, so any use of f within S is dependent on the template parameters of S.

14.6.2.3 [temp.dep.constexpr] paragraph 2:

An id-expression is value-dependent if:

...

— it names a static member function that is a dependent member of the current instantiation

This applies to 'f' here, which is a dependent member of the current instantiation. 14.6.2.1 [temp.dep.types] paragraph 4:

...

A name is a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member of a class that is the current instantiation.

Consequently sizeof(f(0)) is dependent, I<sizeof(f(0))> is dependent, and I<sizeof(f(0))>::Type needs typename to identify it as a type and not a data member.

gcc is therefore right to complain.

MSVC does late lookup with templates, so doesn't complain. This is a bug, but I don't think they ever intend to fix it.

Clang appears to have a bug here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!