如何推断依赖的非类型模板参数?简化数组模板类实例化
简化std::array作为非类型模板参数的类实例化写法
问题背景
现有一个以std::array为非类型模板参数的C++类模板,用于在编译阶段完成配置校验。当前实例化类时必须同时指定数组大小和数组实例(如MyClass<4, valid_config> a;),但数组大小可从数组参数中自动推导,希望简化为MyClass<config> m;的写法,且不能更换容器类型。
解决方案
方案1:C++20 原生自动推导(推荐)
C++20支持非类型模板参数的占位符类型推导,可以直接让编译器自动推导std::array的大小模板参数,无需手动指定。修改后的代码如下:
#include <array> // 用auto自动推导std::array的大小参数 template<const std::array<int, auto>& config> class MyClass { public: MyClass(); private: static constexpr bool configIsValid(); }; template<const std::array<int, auto>& config> MyClass<config>::MyClass() { static_assert(configIsValid(), "Config size must be greater than 3"); } template<const std::array<int, auto>& config> constexpr bool MyClass<config>::configIsValid() { return config.size() > 3; } int main() { static constexpr std::array<int, 4> valid_config{1,2,3,4}; MyClass<valid_config> a; // 仅需传入数组实例,大小自动推导 static constexpr std::array<int, 3> invalid_config{5,6,7}; // MyClass<invalid_config> b; // 编译失败,触发static_assert校验 return 0; }
这种写法利用了C++20的新特性,std::array<int, auto>中的auto会自动匹配数组的实际大小,实例化时只需要传入数组变量即可。
方案2:模板别名包装(兼容C++17及更早)
如果需要兼容C++17或更早版本,可以通过模板别名来包装原类模板,自动推导数组大小:
#include <array> // 保留原类模板结构不变 template<std::size_t config_size, const std::array<int, config_size>& config> class MyClass { public: MyClass(); private: static constexpr bool configIsValid(); }; template<std::size_t config_size, const std::array<int, config_size>& config> MyClass<config_size, config>::MyClass() { static_assert(configIsValid()); } template<std::size_t config_size, const std::array<int, config_size>& config> constexpr bool MyClass<config_size, config>::configIsValid() { return config.size() > 3; } // 定义模板别名,自动推导数组大小 template<const auto& config> using MyClassSimple = MyClass<config.size(), config>; int main() { static constexpr std::array<int, 4> valid_config{1,2,3,4}; MyClassSimple<valid_config> a; // 使用别名简化实例化 static constexpr std::array<int, 3> invalid_config{5,6,7}; // MyClassSimple<invalid_config> b; // 编译失败 return 0; }
模板别名MyClassSimple会通过config.size()自动获取数组大小,传递给原类模板的config_size参数,从而实现简化实例化的效果。
内容的提问来源于stack exchange,提问作者mattday
相关产品推荐
相关产品推荐

