Reputation: 4838
I need to create an array with all values in a range. I can't set values after creating it, because array must be constexpr.
template<int FIRST, int LAST>
struct Foo
{
static constexpr int array[LAST - FIRST + 1] = ???;
};
For exemple Foo<3, 7>::array;
should be equivalent to static constexpr int array[5] = {3, 4, 5, 6, 7};
.
Is it even possible?
Upvotes: 1
Views: 2653
Reputation: 137330
Yes, it can be done in C++11. No, it's not pretty. You essentially need to reimplement C++14's compile-time integer sequences.
///////////////// Reimplement compile-time integer sequences ///////////////////////
// There's plenty of better implementations around.
// This one is similar to libstdc++'s implementation.
template<class T, T... Ints>
struct integer_seq {
using next = integer_seq<T, Ints..., sizeof...(Ints)>;
static constexpr std::size_t size() { return sizeof...(Ints); }
};
template<class T, int Len>
struct seq_builder{
static_assert(Len > 0, "Length must be nonnegative");
using type = typename seq_builder<T, Len-1>::type::next;
};
template<class T>
struct seq_builder<T, 0>{
using type = integer_seq<T>;
};
template<class T, int length>
using make_int_sequence = typename seq_builder<T, length>::type;
/////////////////// Actual stuff starts here/////////////////////////////////
template<int FIRST, int LAST, class = make_int_sequence<int, LAST+1-FIRST>>
struct Foo;
template<int FIRST, int LAST, int... SEQ>
struct Foo<FIRST, LAST, integer_seq<int, SEQ...>>
{
static constexpr int array[sizeof...(SEQ)] = {(FIRST+SEQ)...};
};
template<int FIRST, int LAST, int... SEQ>
constexpr int Foo<FIRST, LAST, integer_seq<int, SEQ...>>::array[sizeof...(SEQ)];
Demo.
Upvotes: 5
Reputation: 39013
It's possible in the proposed C++14 standard. I don't think it's possible with C++11.
If you really must do that, and don't just have a few such arrays that you can hard-code, you can resort to C macros. Apparently there are some libraries that help you perform loops in macros .
Upvotes: 0