geza
geza

Reputation: 29962

Is it possible to iterate through enum members in a constexpr function, so the values are constexpr?

Suppose that I want to create a general system which can store variable-width integers together. In this system, we can use an enum, which contain member names (this enum members have consecutive values [0;count)):

enum class Group1 {
    AttrA,
    AttrB,
    AttrC,
};

I add inline constexpr specialization, which tells, how many members are there:

template <typename TYPE>
inline constexpr int count = -1;

template <>
inline constexpr int count<Group1> = 3; // Group1 has 3 members (AttrA/B/C)

And I add inline constexpr specializations which describes each members width:

template <auto VALUE>
inline constexpr int nBits = -1;

template <>
inline constexpr int nBits<Group1::AttrA> = 3; // AttrA need 3 bits of storage
template <>
inline constexpr int nBits<Group1::AttrB> = 2;
template <>
inline constexpr int nBits<Group1::AttrC> = 4;

Now, I'd like to have a general constexpr function , which can calculate summed width (of any type, not just Group1):

template <typename TYPE>
constexpr int summedWidth() {
    int r = 0;
    for (int i=0; i<count<TYPE>; i++) {
        r += nBits<static_cast<TYPE>(i)>;
    }
    return r;
}

However, this doesn't compile, because of the r += nBits... line:

error: non-type template argument is not a constant expression

Is it possible to create a compilable summedWidth() function (or any other solution, which provides a compile-time constant)?

Upvotes: 3

Views: 679

Answers (1)

Brian Bi
Brian Bi

Reputation: 119184

Use std::make_integer_sequence to expand count<TYPE> into a pack that you can fold over:

template <typename TYPE, int... ints>
constexpr int summedWidthHelper(std::integer_sequence<int, ints...>) {
    return (0 + ... + nBits<static_cast<TYPE>(ints)>);
}

template <typename TYPE>
constexpr int summedWidth() {
    return summedWidthHelper<TYPE>(std::make_integer_sequence<int, count<TYPE>>{});
}

Coliru link: http://coliru.stacked-crooked.com/a/28df4b17d071f6e5

Upvotes: 2

Related Questions