我想创建一个只有数字类型
的std::array
别名
template<typename T, std::size_t n, T = std::is_arithmetic<T>::value>
using NumericArray = std::array<T, n>;
这适用于整数
NumericArray<int, 2> i{1, 2};
但是,如果我想要一个浮点数或双精度,我会因非类型模板参数
而出错NumericArray<float, 2> f{1.0f, 2.0f};
还有其他方法可以做到吗?
答案 0 :(得分:10)
如果你想阻止某人使用非算术类型的别名,那么你做错了。
您的代码将允许任何类型的有效模板参数,并且可以从bool
构建而且都是。
正确的解决方案是这样的:
template <typename T, std::size_t n>
using NumericArray = std::enable_if_t<std::is_arithmetic<T>::value, std::array<T, n>>;
为什么您的代码不起作用
看看这部分:
template<typename T, std::size_t n, T = std::is_arithmetic<T>::value>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
它创建一个类型为T的未命名模板参数,并为其设置默认值。
即使std::is_arithmetic<T>::value
为false,只要T
可以构建bool
,代码就会编译。
当然,T
也必须可用作模板参数。 (这就是为什么float
不起作用的原因。浮点类型不能是模板参数。请参阅:Why can't I use float value as a template parameter?)
同样,如果std::is_arithmetic<T>::value
为假,编译器没有理由生成任何错误。
例如,您的代码将允许以下类型:
struct S
{
constexpr S(bool) {}
};
答案 1 :(得分:7)
(希望)我们很快就能用干净的概念写出来:
template <class T>
concept constexpr bool Arithmetic = std::is_arithmetic_v<T>;
template <Arithmetic T, std::size_t n>
using NumericArray = std::array<T, n>;
顺便说一句,这会在gcc 7上用-fconcepts
编译并运行 now 。对于gcc 6,您需要使用std::is_arithmetic<T>::value
在c ++ 14中你也有一些方法。
我更喜欢:
template <class T, std::size_t n,
class Enable = std::enable_if_t<std::is_arithmetic<T>::value>>
using NumericArray = std::array<T, n>;
中为您提供了另一种方式