распаковать несколько пакетов параметров для инициализации двумерного массива

Я пытаюсь распаковать несколько пакетов параметров, чтобы arr[i][j] = X(i,j). Однако я получаю следующую ошибку с текущим подходом ниже. Существуют ли подходы для достижения вышеуказанного с использованием С++14/17?

      // Non copyable and default constructable
struct X
{
    X(const X&) = delete;
    X(int x, int y) : _x(x), _y(y)
    {}
    int _x;
    int _y;
};

X getX(int i, int j)
{
    return X(i,j);
}


template <std::size_t ...Xidx, std::size_t ... Yidx>
auto make_2d_array(std::index_sequence<Xidx...>, std::index_sequence<Yidx...>)
{
    std::array<std::array<X,sizeof...(Xidx)>, sizeof...(Yidx)> arr = {getX(Xidx, Yidx)...};
    return arr;
}

static constexpr std::size_t M = 5;
static constexpr std::size_t N = 6;

int main()
{
    std::array<std::array<X,M>, N> arr = make_2d_array(std::make_index_sequence<M>{}, std::make_index_sequence<N>{});
}

Ошибка

      <source>:26:87: error: pack expansion contains parameter packs 'Xidx' and 'Yidx' that have different lengths (5 vs. 6)
    std::array<std::array<X,sizeof...(Xidx)>, sizeof...(Yidx)> arr = {getX(Xidx, Yidx)...};
                                                                           ~~~~  ~~~~ ^
<source>:35:42: note: in instantiation of function template specialization 'make_2d_array<0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5>' requested here
    std::array<std::array<X,M>, N> arr = make_2d_array(std::make_index_sequence<M>{}, std::make_index_sequence<N>{});
                                         ^
1 error generated.
Compiler returned: 1

1 ответ

я бы сделал это

      template<std::size_t... XIs, std::size_t... YIs>
std::array<std::array<X, sizeof...(XIs)>, sizeof...(YIs)> make_2d_array(std::index_sequence<XIs...>, std::index_sequence<YIs...>)
{
    return {
        [](auto YI) -> std::array<X, sizeof...(XIs)> {
            return {getX(XIs, YI)...};
        }(YIs)...
    };
}

Да, это несколько ужасно. Принцип просто в том, что нам нужно синтаксически разделить XIsа также YIsдостаточно, чтобы каждый ...расширение распаковывает только одно из них, и нам нужно два расширения, чтобы сделать «продукт» вместо «архивирования».

Другие вопросы по тегам