xmh0511
xmh0511

Reputation: 7369

Is a nested class name be considered as a current instantiation when it is used in a enclosing class template

According to the rule:
temp.res#3

When a qualified-id is intended to refer to a type that is not a member of the current instantiation ([temp.dep.type]) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. If the qualified-id in a typename-specifier does not denote a type or a class template, the program is ill-formed.

That means, when a member of a current instantiation is used as a type-specifier it's not necessary to be prefixed by the keyword typename.

Please consider the following code:

#include <iostream>
template<class T>
struct A{
    struct B{
        struct C{
           A::B* p; //#5
        };
      B::C c;  //#3
      A::B::C d; //#4
    };
    A::B a;  //#1
    /*B::C b;*/  //#2
};
int main(){

}

The definition for current instantiation are: temp.dep.type#1

A name refers to the current instantiation if it is

  1. in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class,
  2. in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <> (or an equivalent template alias specialization),
  3. in the definition of a nested class of a class template, the name of the nested class referenced as a member of the current instantiation, or

The declaration at #1 is well-formed due to the first bullet of current instantiation. that is, at #1, the name A is the name of current instantiation, similar for #3.

#4 is well-formed, because it obeys the third bullet of current instantiation, hence for A::B, where B is the name of current instantiation.

However, I can't understand why #2 is ill-formed, in other words, it require the keyword typename, According to the first bullet, Isn't the name of the nested class be considered as a name of current instantiation?

Frankly, I don't know how to understand the first bullet. At least, I feel that the sentence is vague. Does it mean these injected-class-names(primary class name or nested class name) are all considered as a name of current instantiation as long as in one of the definitions listed in the sentence? #2 seems not support this interpretation.

What I can infer from the example is, The enclosing class name in a nested class can be considered as a name of current instantiation but not the other way around. If understand the sentence in this way, It can understand why the code at #5 is well-formed.

So, how to read the first bullet correctly? Do you agree the sentence is vague?

Upvotes: 2

Views: 100

Answers (1)

dfrib
dfrib

Reputation: 73186

Is a nested class name be considered as a current instantiation when it is used in a enclosing class template?

No.

However, as with many other passages of the standard, paragraph [temp.dep.type]/1.1 is indeed a mouthful:

A name refers to the current instantiation if it is

  • (1.1) in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class, [...]

and we may need to break it down into the different cases to see that it does not apply to a nested-class-name when in the definition of class template where, in turn, the nested class is defined:

A name refers to the current instantiation if it is,

  • in the definition of a class template, the injected-class-name of the class template ["or nested class" does not apply for this case]
  • in the definition of a nested class of a class template, the injected-class-name of the class template or [the] nested class
  • in the definition of a member of a class template, the injected-class-name of the class template ["or nested class" does not apply for this case]
  • in the definition of a member of a nested class of a class template, the injected-class-name of the class template or [the] nested class

where I have emphasized the connection of the "if it is in the definition of a X (of a Y), the injected-class-name of the X (or [the] Y)". Noting particularly that when the definition is of a class template (when X is class template), there is no "a nested class" to refer back to at the latter part, when describing the "injected-class-name of the ...".

Conversely, there is no way interpret [temp.dep.type]/1.1 as

" in the definition of a class template, the injected-class-name of the class template or any nested class of the class template "

Thus, in your example, #2, we are in the definition of a class template (namely A), meaning only the name of the class template itself, namely A, refers to the current instantiation.


Do you agree the sentence is vague?

Given the above, I would not say that it is vague (as this would imply some ambiguity, which I cannot see), but possible needlessly complex. It could arguably be clearer if [temp.dep.type]/1.1 was split into two separate paragraphs:

A name refers to the current instantiation if it is

  • (1.1a) in the definition of a class template, or a member of a class template, the injected-class-name of the class template,
  • (1.1b) in the definition of a nested class of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class, [...]

Upvotes: 2

Related Questions