You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}};

原理说明

  1. 模板参数改为非类型参数N:直接用数组大小作为模板参数,贴合数组本质,避免冗余的类型参数。
  2. 模板构造函数:接受任意数量的Args参数,利用C++聚合初始化规则,将每个{pin, state}隐式转换为Relay对象,完成内部数组的初始化。
  3. 推导指引:告诉编译器如何根据构造函数的参数数量推导模板参数N,无需显式指定数组大小。

兼容性验证

  • 完全兼容C17,推导指引是C17标准特性,符合版本要求。
  • 未使用initializer_list,适配AVR/Arduino的C++环境。
  • 每个{pin, state}会被编译器隐式转换为Relay实例,无需显式编写Relay{}。

内容的提问来源于stack exchange,提问作者Fred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:17:54