c++c++17variadic-templatestemplate-meta-programmingindex-sequence

Creating a structure with an expanded index sequence


I want to be able to use parameter pack expansion in the initializer list of constructors. Is the best way to achieve this, to endow my class with a parameter pack template argument? Here is an example of what I mean: https://coliru.stacked-crooked.com/a/e699c4cd035e0b1c

#include <utility>
#include <iostream>

template<typename T, std::size_t...Is>
struct base_vec
{
    constexpr static std::size_t N = sizeof...(Is);
    T e[N];
    base_vec() : e{} {}
    explicit base_vec(const T& s) : e{((void)Is,s)...} {}
};


template<typename T, std::size_t...Is>
std::ostream& operator<<(std::ostream& lhs, const base_vec<T,Is...>& rhs)
{
    return (std::cout << ... << rhs.e[Is]);
}



template<typename T, std::size_t...Is>
constexpr auto getVecIs(std::index_sequence<Is...> seq)
{
    return base_vec<T, Is...>{};
}




template<typename T, std::size_t N>
using vec = decltype(getVecIs<T>(std::declval<std::make_index_sequence<N>>()));

int main()
{
    vec<int,3> v(2);
    std::cout << v << "\n";
    return 0;
}

Note the trivial expansion e{((void)Is,s)...}. Is this an ok practice, or am I missing some minus of this approach (except for the fact that now my structure will have a whole parameter pack, as opposed to a single size_t N)?


Solution

  • You can move the expansion entirely inside the class:

    template<typename T, std::size_t N>
    struct vec
    {
    public:
        T e[N];
        vec() : e{} {}
        explicit vec(const T& s) : vec{s, std::make_index_sequence<N>{}} {}
    private:
        template <std::size_t ... Is>
        vec(const T& s, std::index_sequence<Is...>) : e{(Is, s)...} {}
    };