C++17下无需指定模板参数声明RelayArray的实现求助
实现无需显式指定类型和数量的RelayArray声明
问题背景
现有代码如下:
struct Relay { int pin; bool state; }; template<typename... Relays> class RelayArray { private: Relay array[sizeof...(Relays)]; public: RelayArray(Relays... relays) : array{relays...} {} }; // 当前需要显式指定模板参数或每个元素写Relay{} RelayArray<Relay, Relay, Relay> myRelayArray{{2, true}, {4, false}, {6, true}}; RelayArray myRelayArray2{Relay{2, true}, Relay{4, false}, Relay{6, true}};
期望实现无需指定元素数量和类型,直接用聚合初始化列表声明:
RelayArray myRelayArray{{2, true}, {4, false}, {6, true}};
限制条件:兼容C++17及更早版本,不能使用initializer_list(AVR/Arduino环境不支持)。
解决方案
通过类模板参数推导(CTAD)和模板构造函数结合,同时添加推导指引来实现需求。修改后的代码如下:
#include <utility> // 用于std::forward struct Relay { int pin; bool state; }; template<std::size_t N> class RelayArray { private: Relay array[N]; public: // 模板构造函数,接受任意可转换为Relay的参数 template<typename... Args> constexpr RelayArray(Args&&... args) : array{std::forward<Args>(args)...} {} // 可选:添加访问数组元素的方法 Relay& operator[](std::size_t idx) { return array[idx]; } const Relay& operator[](std::size_t idx) const { return array[idx]; } }; // C++17推导指引:根据构造函数参数数量推导N的值 template<typename... Args> RelayArray(Args&&...) -> RelayArray<sizeof...(Args)>; // 现在可以直接按期望方式声明 RelayArray myRelayArray{{2, true}, {4, false}, {6, true}};
原理说明
- 模板参数改为非类型参数N:直接用数组大小作为模板参数,贴合数组本质,避免冗余的类型参数。
- 模板构造函数:接受任意数量的
Args参数,利用C++聚合初始化规则,将每个{pin, state}隐式转换为Relay对象,完成内部数组的初始化。 - 推导指引:告诉编译器如何根据构造函数的参数数量推导模板参数
N,无需显式指定数组大小。
兼容性验证
- 完全兼容C17,推导指引是C17标准特性,符合版本要求。
- 未使用
initializer_list,适配AVR/Arduino的C++环境。 - 每个
{pin, state}会被编译器隐式转换为Relay实例,无需显式编写Relay{}。
内容的提问来源于stack exchange,提问作者Fred
相关产品推荐
相关产品推荐

