C++17空基类聚合初始化时如何避免冗余{}?求解决方案
解决C++17空基类聚合初始化冗余的问题
你遇到的这个问题确实挺闹心的——当基类只提供函数、没有任何数据成员时,派生类做聚合初始化必须额外加一对空括号来初始化基类,写起来特别啰嗦。下面给你提供几种可行的解决思路,涵盖C++17及更早版本的替代方案:
方案一:将派生类改为非聚合类,添加构造函数(C++17/11/03通用)
这是最直接的解决办法:给派生类添加一个接受初始化列表的构造函数,让构造函数负责处理数组成员的初始化,用户就不用再操心基类的初始化细节了。
C++17实现(支持编译期初始化)
#include <cstddef> #include <initializer_list> struct base_pod { // 示例友元比较运算符 friend bool operator==(const base_pod&, const base_pod&) = default; }; template<typename T, std::size_t N> struct der_pod : public base_pod { T k[N]; // constexpr构造,支持编译期初始化 constexpr der_pod(std::initializer_list<T> init) noexcept { std::size_t idx = 0; for (const auto& val : init) { if (idx >= N) break; k[idx++] = val; } // 数组剩余元素会自动默认初始化(比如int会初始化为0) } }; int main() { der_pod<int, 2> dp{3, 3}; // 直接初始化,无需空括号 }
C++11/03适配版本
如果是C11,可以保留初始化列表构造;C03则需要改用数组参数传递初始化值:
// C++03版本 #include <cstddef> struct base_pod { // 友元函数定义 }; template<typename T, std::size_t N> struct der_pod : public base_pod { T k[N]; der_pod(const T (&init_arr)[N]) { for (std::size_t i = 0; i < N; ++i) { k[i] = init_arr[i]; } } }; int main() { int init[] = {3, 3}; der_pod<int, 2> dp(init); }
方案二:重构基类逻辑,避免继承空基类(C++17/11)
如果想保持派生类的聚合特性,同时摆脱冗余括号,可以把原来基类的函数逻辑改成独立的模板自由函数,不再通过继承实现:
#include <cstddef> // 把原基类的函数改成独立模板函数,无需继承 template<typename T, std::size_t N> bool operator==(const der_pod<T, N>& lhs, const der_pod<T, N>& rhs) { for (std::size_t i = 0; i < N; ++i) { if (lhs.k[i] != rhs.k[i]) return false; } return true; } template<typename T, std::size_t N> struct der_pod { // 不再继承base_pod T k[N]; }; int main() { der_pod<int, 2> dp{3, 3}; // 完全正常的聚合初始化,无冗余括号 }
这种方式下,派生类就是普通的聚合类,初始化体验和没有基类时完全一致,同时原基类的函数逻辑通过模板自由函数实现,效果和继承时完全相同。
方案三:升级到C++20(最省心的方案)
如果你的项目可以升级到C20,标准对聚合初始化规则做了优化:当基类是空聚合类时,初始化列表中可以直接省略对应的空括号。也就是说你原来的代码在C20下可以直接写成:
der_pod<int, 2> dp{3, 3}; // C++20中编译通过,无需空括号
这是最省事的解决方案,但需要依赖C++20的编译器支持。
内容的提问来源于stack exchange,提问作者Li Chen
相关产品推荐
相关产品推荐

