michal915
michal915

Reputation: 126

Create alias for numeric array

I want to create an alias of std::array with only numeric types

template<typename T, std::size_t n, T = std::is_arithmetic<T>::value>
using NumericArray = std::array<T, n>;

this works correctly with an integer

NumericArray<int, 2> i{1, 2};

But if I want a float or double I have an error due to the non-type template parameter

NumericArray<float, 2> f{1.0f, 2.0f};

There is some other way to do this?

Upvotes: 9

Views: 445

Answers (2)

bolov
bolov

Reputation: 75755

(Hopefully) very soon we will be able to write it very cleanly using concepts:

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

And btw, this compiles and runs now on gcc 7 with -fconcepts. For gcc 6 you need to use std::is_arithmetic<T>::value


In c++14 you have some ways too.

I prefer:

template <class T, std::size_t n,
          class Enable = std::enable_if_t<std::is_arithmetic<T>::value>>
using NumericArray = std::array<T, n>;

@holyblackcat gave you another way in his answer

Upvotes: 7

HolyBlackCat
HolyBlackCat

Reputation: 96334

If you want to prevent someone form using this alias with non-arithmetic types, then you did it wrong.

Your code will allow any type that is a valid template argument and can be constructed from bool and that's all.

The proper solution would be something like this:

template <typename T, std::size_t n>
using NumericArray = std::enable_if_t<std::is_arithmetic<T>::value, std::array<T, n>>;

Why your code doesn't work:

Look at this part:

template<typename T, std::size_t n, T = std::is_arithmetic<T>::value>
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It creates an unnamed template argument of type T and sets a default value for it.

Even if std::is_arithmetic<T>::value is false, the code will compile as long as T can be constructed from bool.

Of course, T must be also usable as a template argument. (That's why float does not work. Floating-point types can't be template arguments. See this: Why can't I use float value as a template parameter?)

Again, there is just no reason for the compiler to generate any errors if std::is_arithmetic<T>::value is false.

For example, your code will allow following type:

struct S
{
    constexpr S(bool) {}
};

Upvotes: 10

Related Questions