C++17及更早版本中指定RelayArray的D参数并推导N参数
问题:C++17及更早版本中指定RelayArray的D参数并自动推导N
先看原代码实现:
struct Relay { int pin; bool state; }; template<std::size_t N, uint8_t D = 10> class RelayArray { private: Relay array[N]; // 不可使用STL容器 EWMA_average<D> ewma_average; public: RelayArray(const Relay(&ref)[N]) {} }; // 当前可自动推导N=3,D使用默认值10 RelayArray myRelayArray{{{2, true}, {4, false}, {6, true}}};
当前问题:若想仅指定D参数(比如D=5),直接写RelayArray<5>会把5解析为第一个模板参数N,无法满足需求。以下是两种可行解决方案:
方案1:调换模板参数顺序
将D设为第一个模板参数,N作为第二个且不设默认值。这样指定D时,N可从初始化列表自动推导:
struct Relay { int pin; bool state; }; template<uint8_t D = 10, std::size_t N> class RelayArray { private: Relay array[N]; EWMA_average<D> ewma_average; public: RelayArray(const Relay(&ref)[N]) {} }; // 指定D=5,自动推导N=3 RelayArray<5> myRelayArray{{{2, true}, {4, false}, {6, true}}}; // 使用默认D=10,自动推导N=3(需加<>表示使用默认参数) RelayArray<> myRelayArray{{{2, true}, {4, false}, {6, true}}};
该方案无需额外代码,完全兼容C++17及更早版本,缺点是需要调整原模板的参数顺序,旧有代码中指定双参数的写法需同步修改(如RelayArray<3,5>需改为RelayArray<5,3>)。
方案2:使用工厂函数推导N
保持原类模板的参数顺序不变,通过工厂函数固定D参数并推导N:
C++17版本(支持auto函数参数)
struct Relay { int pin; bool state; }; template<std::size_t N, uint8_t D = 10> class RelayArray { private: Relay array[N]; EWMA_average<D> ewma_average; public: RelayArray(const Relay(&ref)[N]) {} }; // 工厂函数:指定D,自动推导数组大小N template<uint8_t D> auto makeRelayArray(const auto& arr) { return RelayArray<sizeof(arr)/sizeof(arr[0]), D>(arr); } // 使用方式:指定D=5,自动推导N=3 auto myRelayArray = makeRelayArray<5>({{2, true}, {4, false}, {6, true}});
C++14及更早版本(显式指定N的推导)
struct Relay { int pin; bool state; }; template<std::size_t N, uint8_t D = 10> class RelayArray { private: Relay array[N]; EWMA_average<D> ewma_average; public: RelayArray(const Relay(&ref)[N]) {} }; // 工厂函数:指定D,推导数组大小N template<uint8_t D, std::size_t N> RelayArray<N, D> makeRelayArray(const Relay(&ref)[N]) { return RelayArray<N, D>(ref); } // 使用方式:指定D=5,自动推导N=3 auto myRelayArray = makeRelayArray<5>({{2, true}, {4, false}, {6, true}});
该方案无需修改原类结构,适配性更强,适合已有代码依赖原模板参数顺序的场景。
内容的提问来源于stack exchange,提问作者Fred
相关产品推荐
相关产品推荐

