类在数组上进行模板化,该数组代表该类的特定配置。这允许在编译时检查配置。这是一个完整的简单示例:
#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);
}
int main()
{
static constexpr std::array<int, 4> valid_config{1,2,3,4};
MyClass<4, valid_config> a;
static constexpr std::array<int, 3> invalid_config{5,6,7};
// MyClass<3, invalid_config> b; // This will fail to compile
return 0;
}
这没问题,但是第一个模板参数可以从第二个模板参数推断出来,所以我更愿意写:
MyClass<config> m;
代替:
MyClass<config_size, config> m;
有什么办法可以做到这一点吗?
数组可能会被包装,但我无法使用不同的容器。
我认为你提出的问题的答案是“不,你不能”——必须指定非类型模板参数的类型。
还有一些替代方法:
在 C++20 中,您可以编写一个
consteval
函数,它返回正确类型的实例。
template<typename C>
consteval auto deduceMyClass(C& config) {
// Unnecessary but possible: static_assert(std::is_same_v<std::array<int, config.size()>, C>);
return MyClass<config.size(), config>{};
}
在 C++17(也可能是 14 和 11,我的记忆很模糊)中,您可以为此使用推导指南,但代价是使配置引用构造函数参数而不是模板参数。