Stack Danny
Stack Danny

Reputation: 8126

simple way to convert parameter pack to array at compile time

is there a simple way to create an std::array from a parameter pack at compile time?

constexpr auto array = to_array<int>(1, 2, 3, 'a', 5.5f);

there are existing solutions:

what would be a clean way to implement this?

Upvotes: 1

Views: 1245

Answers (2)

max66
max66

Reputation: 66200

What about simply

template <typename T, typename... Args>
constexpr std::array<T, sizeof...(Args)> to_array (Args && ... args)
 { return {{ std::forward<Args>(args)... }}; }

?

Or, maybe, if you want to add the static_cast

template <typename T, typename... Args>
constexpr std::array<T, sizeof...(Args)> to_array (Args && ... args)
 { return {{ static_cast<T>(std::forward<Args>(args))... }}; }

and using CTAD and auto return placeholder, you can reduce a little the typewriting

template <typename T, typename... Args>
constexpr auto to_array (Args && ... args)
 { return std::array{ static_cast<T>(std::forward<Args>(args))... }; }

Upvotes: 4

Stack Danny
Stack Danny

Reputation: 8126

A straightforward solution is to expand the parameter pack while increasing an index to copy the values into the array:

template<typename T, typename... Args>
constexpr auto to_array(Args&&... args) {
    std::array<T, sizeof...(Args)> result{};

    unsigned ctr = 0u;
    ((result[ctr++] = static_cast<T>(args)), ...);
    return result;
}

to show how this function would be callable with an std::tuple one can unpack the tuple using an std::integer_sequence:

template<typename T, typename... Args>
constexpr auto to_array(std::tuple<Args...> tuple) {

    auto unpack_tuple = [&]<class Tuple, size_t... Ints>(Tuple&& tuple, std::index_sequence<Ints...>) {
        return to_array<T>(std::get<Ints>(tuple)...);
    };

    return unpack_tuple(tuple, std::make_index_sequence<sizeof...(Args)>{});
}

and using them:

int main() {
    constexpr auto a = to_array<int>(std::tuple(5, 3, 'a', 1.0));
    constexpr auto b = to_array<int>(5, 3, 'a', 1.0);

    static_assert(a == b);
}

used headers:

#include <array>
#include <tuple>
#include <type_traits>

Upvotes: -1

Related Questions