C++20中如何为结构体指定初始化器设置必填指定符?
C++结构体指定初始化实现必填成员的方案
C++标准原生没有直接支持“必填指定符”的语法,但可以通过以下两种方式模拟你需要的效果:
方法1:利用不可默认构造的标记类型(完美匹配示例需求,C++11及以上)
定义一个无法默认构造的标记类型,将必填成员的类内初始值设为该类型的实例,当用户未显式初始化必填成员时,编译器会直接触发错误:
// 定义标记类型,禁止默认构造 struct required_t { constexpr required_t() = delete; }; inline constexpr required_t required{}; struct A { int x = required; // 标记x为必填成员 int y = 0; // y带有默认初始值 }; // 合法用法 A b{.x = 1, .y = 2}; A a{.x = 1}; // 非法用法,编译报错 // A a{.y = 2}; // x未显式初始化,尝试用required初始化失败 // A a; // 默认初始化时x尝试用required初始化失败
原理:聚合初始化规则中,未被显式指定的成员会使用类内初始值。由于required_t的默认构造被删除,未初始化x的操作会直接触发编译错误,完美实现你需要的约束。
方法2:构造函数强制必填(兼容C++20指定初始化)
如果可以接受结构体为非聚合类型,通过构造函数强制传入必填成员,同时给可选成员设置默认参数,C++20起还支持指定初始化语法:
struct A { int x; int y; // 强制传入x参数,y默认值设为0 explicit A(int x_val, int y_val = 0) : x(x_val), y(y_val) {} }; // 合法用法(C++20及以上支持指定初始化) A b{.x = 1, .y = 2}; A a{.x = 1}; // 非法用法,编译报错 // A a{.y = 2}; // 无匹配的构造函数 // A a; // 无默认构造函数
关于指定初始化的补充说明(翻译自cppreference相关内容)
指定初始化器允许通过成员名称而非声明位置来初始化聚合成员,语法为.成员名 = 初始化器,C++20起可省略=写成.成员名{初始化器}。
- C++20之前,指定初始化器必须遵循成员的声明顺序,且只能用于聚合类型;
- C++20起,允许乱序使用指定初始化器,同时非聚合类型也可通过指定初始化器调用构造函数,但未指定的成员仍会按声明顺序初始化(使用类内初始值或零初始化)。
内容的提问来源于stack exchange,提问作者Barry McNamara
相关产品推荐
相关产品推荐

