Mathias
Mathias

Reputation: 1476

Compile time array from C++ template parameter pack

How can I at compile time create for example an std::array from a template parameter pack?

This shows what I need, but without a parameter pack.

template<typename T1, typename T2, typename T3>
struct ToInfoArray
{
    static constexpr std::array<Info, 3> value = { { T1::info, T2::info, T3::info } };
};

Live demo demonstrating the intended usage

Bonus question: Would you use std::array, array[] or std::initializer_list as type for InfoArray?

Upvotes: 11

Views: 8436

Answers (2)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48447

template <typename... Ts>
struct ToInfoArray
{
    static constexpr std::array<Info, sizeof...(Ts)> value = { { Ts::info... } };
};

DEMO

Would you use std::array, array[] or std::initializer_list as type for InfoArray?

std::array<T,N>. It's an aggregate that behaves (with comparable performance) just like a regular array, but provides an additional interface for operating on its elements; itself, it's a copyable type.

std::initializer_list is not an option here for numerous reasons. Once it's used as a data member (with an in-class initializer), the elements it stores are invalidated after any of constructors' execution. It's not guaranteed to be a literal type, thus it can't be marked as constexpr. Its size is not usable (accessible) in constant expressions. It doesn't provide random access logic (without resorting to pointer arithmetic); the only way to enumerate its elements is to iterate from begin() to end(), which in addition yields pointers to constant items. std::initializer_list was designed to serve primarily as a function parameter.

Upvotes: 11

Barry
Barry

Reputation: 302852

With C++14, you can simply make it a variable template:

template <typename... Ts>
constexpr std::array<Info, sizeof...(Ts)> value{{Ts::info...}};

Otherwise, the correct syntax for your usage is:

template <typename... Ts>
struct ToInfoArray
{
    static constexpr std::array<Info, sizeof...(Ts)> value{{Ts::info...}};
};

And strongly prefer std::array<> to raw arrays or an initializer_list.

Upvotes: 3

Related Questions