为数值数组创建别名

时间:2016-09-16 07:29:46

标签: c++ c++11 c++14

我想创建一个只有数字类型

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

还有其他方法可以做到吗?

2 个答案:

答案 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>;

@holyblackcathis answer

中为您提供了另一种方式