C++如何构造可作为非类型模板参数的structural类型可变复合结构
问题原因
C++20起支持template<auto>形式的非类型模板参数,但仅允许**结构类型(structural type)**作为该类参数的类型。结构类型要求所有非静态数据成员为public属性,且成员本身的类型也属于结构类型。标准库的std::tuple未被要求以公开聚合的形式实现,因此不属于结构类型,包含std::tuple成员的Composite类型自然也无法作为非类型模板参数传入,触发编译失败。
解决方案
自定义符合结构类型要求的聚合tuple实现,替换原有代码中的std::tuple即可。
自定义结构类型tuple实现
template<typename... Ts> struct structural_tuple; // 空tuple特化 template<> struct structural_tuple<> {}; // 递归特化 template<typename T, typename... Rest> struct structural_tuple<T, Rest...> { T value; structural_tuple<Rest...> rest; constexpr structural_tuple() = default; constexpr structural_tuple(T v, Rest... r) : value(v), rest(r...) {} }; // 辅助get函数,用于按索引访问元素 template<size_t I, typename T, typename... Rest> constexpr auto& get(structural_tuple<T, Rest...>& t) { if constexpr (I == 0) { return t.value; } else { return get<I-1>(t.rest); } } template<size_t I, typename T, typename... Rest> constexpr const auto& get(const structural_tuple<T, Rest...>& t) { if constexpr (I == 0) { return t.value; } else { return get<I-1>(t.rest); } }
业务代码修改
仅需要将Composite结构体中的std::tuple替换为上述自定义的structural_tuple,并调整对应构造逻辑即可:
// 复合配置修改为使用自定义structural_tuple template<typename... Parts> struct Composite { structural_tuple<Parts...> parts; }; int main() { constexpr Basic a = Basic{}; constexpr Annotated b{a, 12}; constexpr Composite c{structural_tuple{a, b}}; static_assert(proc<a>{}.foo() == 0); static_assert(proc<b>{}.foo() == 1); static_assert(proc<c>{}.foo() == 2); // 可正常编译通过 }
原理说明
自定义的structural_tuple属于公开聚合类型,所有非静态成员均为public,且成员类型都符合结构类型要求,因此它本身也属于结构类型。包含它的Composite类型自然满足结构类型的要求,可以作为非类型模板参数正常使用。如果需要更完整的tuple能力(比如结构化绑定、比较运算符等),只需在structural_tuple中补充对应的constexpr实现即可,不会破坏其结构类型的属性。
内容的提问来源于stack exchange,提问作者user4442671
相关产品推荐
相关产品推荐

