Why can't we use a nested type through an expression to access a class?

I am trying to understand why we cannot use a nested type through an expression to access the class. For example, we have the following class:

struct U { struct A { static int v; int a; }; struct B { int b; }; }; U a; typedef aA T; //'a' does not name a type int main() { std::cout << typeid(aA).hash_code(); //invalid use of 'struct U::A' struct aA b; //trying to declare a variable of type U::A //error: expected unqualified-id before '.' token aA b; //the same as above //error: expected unqualified-id before '.' token aAv = 5; //error: expected unqualified-id before '.' token } 

Demo

The standard says:

Section N3797::5.2.5/2 [expr.ref]

For the first parameter (period), the first expression must have the full class type. For the second option (arrow), the first expression should have a pointer to the full class type. The expression E1-> E2 is converted to the equivalent form (* (E1)). E2; the rest of 5.2.5 will only address the first option (dot). In any case, the id expression must indicate a member of the class or one of its base classes.

While section N3797::9.2/1 [class.mem] gives a definition of a class member:

Class members are data members, member functions (9.3), nested types, and counters.

Therefore, I do not see any restrictions on such use of the nested type. Why not?

+5
source share
3 answers

See further in [expr.ref]

(4.4) If E2 is a nested type, the expression E1.E2 is poorly formed.

+4
source

The standard talks about the type of object that a variable represents.
You need to access the scope of the class, not the variable.

And in order to access the members of a nested class from U , you need to create an element from this type, there are two ways to do this:

 struct U { struct A { static int v; int a; } VarNameForA; struct B { int b; }; B VarNameOfB; }; 

Use the scope operator :: to access types.

Here's how you do everything you've tried:

 U a; typedef decltype(a) varType; typedef varType::A nestedType; int main() { std::cout << typeid(U::A).hash_code(); struct U::A b; U u; u.VarNameForA.a = 5; u.VarNameOfB.b = 6; U::A::c = 3; } 

For participants, you use the dot (.) Operator; for types and statics, you need to use the scope :: operator.

+2
source

You are trying to use aA as a type specifier.

The access rules for the class members (5.2.5) that you refer to are valid only for expressions not for type specifiers and type names (5/1: "An expression is a sequence of operators and operands that the calculation defines. An expression can lead to a value and can cause side effects. ").

You should look for rules for type specifiers in section 7.1.6 of the standard. There is no operator here . . In the developed types (7.1.6.3) it is used :: to combine components on the type name.

The clang error message is more explicit than the one you get from your compiler: "cannot use dot operator in type").

By the way, your U is an empty structure (without data) with a single definition of nested types. That is why aAv = 5; also a mistake: there is no lvalue value.

+2
source

Source: https://habr.com/ru/post/1205491/


All Articles