C++类内嵌套结构体成员初始化为何无法使用auto关键字
错误根本原因
这个报错和Inner_t是私有嵌套类型没有任何关联,核心是C++标准对auto关键字的使用限制,以及测试时的场景混淆:
- 第一段报错代码里,
const auto NotStored = Inner_t{-1, -1};是Outer_t的非静态数据成员。在C20标准之前,C语法明确禁止非静态数据成员声明时使用auto做类型推导——不管初始化值的类型是嵌套私有类型还是全局公开类型,只要是非静态类成员,C11/14/17标准下使用auto都会触发这个错误。你使用的clang 13默认采用C14标准,自然会报错。 - 你给出的第二段“可正常编译”的代码,实际上和第一段不是同一个场景:这段代码里的
const auto NotStored = Plain_t{-1, -1};是定义在全局作用域的普通变量,根本不是类成员。而全局变量、局部变量从C++11开始就支持auto类型推导,当然可以正常编译,和Plain_t是否定义在类外部没有关系。你之前误以为是移动Inner_t的位置让代码通过编译,本质是你把变量从类内非静态成员改成了全局变量,刚好符合auto的使用规则。
补充验证和解决方案
- 你注释掉的
const Inner_t NotStored = Inner_t{-1, -1};能正常编译,是因为显式指定了成员类型Inner_t,没有使用auto,完全不受非静态成员禁用auto的规则约束,和类型的访问权限、定义位置无关。哪怕Inner_t是私有嵌套类型,类自身的成员本来就有访问权限,不存在访问限制问题。 - 如果要在C++17及更早标准下在类内用
auto定义常量,可以把成员声明为静态常量表达式:
struct Outer_t{ private: struct Inner_t { int A; int B; }; // C++14/17下可正常编译 static constexpr auto NotStored = Inner_t{-1, -1}; };
- 如果给clang 13加上
-std=c++20编译参数启用C20标准,你最开始写的非静态成员用auto的代码也可以正常编译——C20正式移除了非静态数据成员不能使用auto推导类型的限制。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

