Dudly01
Dudly01

Reputation: 503

How to set length of array alias with scoped enum template argument without casting

My goal is to create an alias for a std::array that sets the length based on an enum template argument. I managed to make it work relying on the conversion of the enum, as seen in my code below.

#include <array>
#include <iostream>

enum class StateRepresentation
{
    Log2 = 1,
    One_hot = 16
};

template <StateRepresentation R>
using State = std::array<int, static_cast<int>(R) * 16>;

int main(void)
{
    const auto curr_repr = StateRepresentation::One_hot;
    auto b = State<curr_repr>{};
    std::cout << "Representation value: " << static_cast<int>(curr_repr) << '\n';
    std::cout << "Array length: " << b.size() << '\n';

    return 0;
}

Would it be possible to achieve the same but without relying on static_cast to obtain the numeric value of the enumerator?

I attempted something along the lines of template specialization as seen below, but failed to make it work:

template <>
using State<StateRepresentation::Log2> = std::array<int, 1 * 16>;

template <>
using State<StateRepresentation::One_hot> = std::array<int, 16 * 16>;

Upvotes: 1

Views: 36

Answers (1)

cigien
cigien

Reputation: 60228

You can use conditional_t to switch on which member of the enum class is used for instantiation:

template <StateRepresentation R>
using State = std::conditional_t<R == StateRepresentation::Log2,
                                 std::array<int, 1 * 16>,
                                 std::array<int, 16 * 16>>;

This avoids the need for the enum class members to have the same values as the ones you want to use in the std::array.

As pointed out in a comment, you could also use a ternary condition in the array parameter itself to pick the size you want

template <StateRepresentation R>
using State = std::array<int, (R == StateRepresentation::Log2 ? 1 : 16) * 16>;

Upvotes: 1

Related Questions