为什么我们不能通过类成员访问表达式使用嵌套类型?

Why can't we use nested type through class-member-access expression?

本文关键字:表达式 访问表 嵌套类型 访问 成员 不能 我们 为什么      更新时间:2023-10-16

我试图理解为什么我们不能通过类成员访问表达式使用嵌套类型。例如,我们有以下类:

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

演示

标准说:

N3797::5.2.5/2 [expr.ref]

对于第一个选项(点),第一个表达式应完整类类型。对于第二个选项(箭头),第一个表达式应具有指向完整类类型的指针。表达式E1->E2为转换为等价形式(*(E1)).E2;5.2.5的剩余部分将只寻址第一个选项(点)。在任何一种情况下id表达式应命名该类或其基类之一的成员

然而,N3797::9.2/1 [class.mem]节给出了类成员的定义:

类的成员是数据成员、成员函数(9.3)、嵌套类型和枚举器。

所以我看不出嵌套类型的这种用法有什么限制。为什么不呢?

在[expr.ref]中进一步查看

(4.4)如果E2是嵌套类型,则表达式E1.E2是错误形式的。

标准讨论的是变量所代表的对象的类型
您需要访问类的作用域,而不是变量。

要从U访问嵌套类的成员,需要从该类型创建一个成员,有两种方法:

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

使用作用域运算符::访问类型。

以下是您尝试的所有操作方法:

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;                          
}

对于使用运算符dot (.)的成员,对于类型和静态,则需要使用scope ::运算符。

您尝试使用a.A作为类型说明符。

您引用的类成员访问规则(5.2.5)仅适用于表达式,而不适用于类型说明符和类型名(5/1:"表达式是指定计算的运算符和操作数序列。表达式可能产生值,并可能产生副作用。")。

您必须在标准的7.1.6节中查找类型说明符的规则。此处未预见到操作员.的使用。详细描述的类型(7.1.6.3)使用::来组合类型名称上的组件。

clang 错误消息比您从编译器中得到的消息更明确:"不能在类型上使用点运算符")。

顺便说一下,您的U是一个空结构(没有数据),只有嵌套类型的定义。这就是为什么a.A.v = 5;也是一个错误:这里没有可以赋值的左值。