C++中模拟匿名结构体声明与动态初始化的更优实现方案问询
C++中模拟匿名结构体声明与动态初始化的更优实现方案问询
我最近在琢磨C++里匿名结构体声明加初始化的写法,想找到更贴近其他语言那种简洁直观的实现方式,先来跟大家聊聊目前的情况和遇到的问题。
在一些编程语言里,我们可以无缝地声明并初始化匿名结构体(或者类似的结构),比如ECMAScript里的写法就很清爽:
function foo_in_ecmascript(x) { let computed = { bar : magic(x), baz : mystery(x), quux : fantasy(x) }; // ... 用 computed.baz、computed.quux 做操作,比如 console.log(`computed.quux is ${computed.quux}`); }
这种写法把变量、字段名和初始化逻辑紧紧绑定在一起,可读性和维护性都很棒。
但在C++里,我们没法直接写出这种“理想型”代码:
void foo(int x) { struct { auto bar = magic(x); auto baz = mystery(x); auto quux = fantasy(x); } computed; // ... 用 computed.baz、computed.quux 做操作 }
问题出在不能在匿名结构体里使用非constexpr的成员初始化器,这段代码根本过不了编译。
我们只能退而求其次,写出能正常编译的版本:
void foo2(int x) { struct { Bar bar; Baz baz; Quux quux; } computed = { magic(x), mystery(x), fantasy(x) }; // ... 用 computed.baz、computed.quux 做操作 }
但这种写法的缺点很突出:
- 代码更长,必须显式写出每个函数的返回类型
- 要格外注意维护字段顺序和初始化值的对应关系,字段越多越容易出错
- 类型、变量名和初始化逻辑是分离的,可读性打了折扣
到了C++20,我们可以用指定初始化器来优化可读性:
void foo3(int x) { struct { Bar bar; Baz baz; Quux quux; } computed = { .bar { magic(x) }, .baz { mystery(x) }, .quux { fantasy(x) } }; // ... 用 computed.baz、computed.quux 做操作 }
这种写法让字段名和初始化值一一对应,可读性提升了不少,但代码行数并没有减少,还重复写了一遍字段标识符。
那现在的问题来了:我们能不能做得更好?有没有办法更接近那种“直观但目前无法直接实现”的匿名类型声明加初始化的形式?
要求说明
- 最终结果必须是一个带有bar、baz、quux三个命名字段的对象,不能是tuple,也不能拆成三个单独的变量
- 支持任何C++标准版本的实现都可以,越老的标准兼容性越好
- 补充:初始化用的函数不一定都接收同一个参数x,它们可以使用foo函数里的本地变量、不同的函数参数,甚至全局变量等
内容来源于stack exchange
相关产品推荐
相关产品推荐

