为什么我们不能通过类成员访问表达式使用嵌套类型?
Why can't we use nested type through class-member-access expression?
我试图理解为什么我们不能通过类成员访问表达式使用嵌套类型。例如,我们有以下类:
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;
也是一个错误:这里没有可以赋值的左值。
- 链表中写入访问冲突的未知原因
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 表观调用前面的表达式必须具有指向 func 类型的指针
- 编写一个函数来删除单链表中的节点(尾部除外),仅授予对该节点的访问权限
- 为什么我在空指针错误(链表)中获取成员访问权限
- 结构化绑定初始值设定项表单 { 赋值表达式 } 对于 clang 上的数组类型失败
- 循环访问资源字符串表
- 在C++中删除双向链表的头节点后出现访问冲突异常
- C++ IDE 不会推断/自动完成对模板类中的 std::array 下标表达式的成员访问
- 循环访问自定义双链表
- 生成 constexpr 字符串表,不能产生常量表达式
- 如何通过不同的指针使用类的对象访问结构?(链表)(C++)
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- QT访问表小部件从单独的线程项目
- 存储并访问表中的不同成员功能
- Lua 访问表的键和值
- 使用 ADO 将原始文件数据插入访问表的 BLOB("OLE 对象")字段
- 从cpprest lambda表达式访问自动变量
- Qt-访问表中的复选框
- 无法在 SQLite 上的命令行上访问表