解包多个参数包以初始化二维数组

问题描述

我正在尝试解压缩多个参数包,以便 arr[i][j] = X(i,j).但是,下面的当前方法出现以下错误。是否有使用 C++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,Yidx)...};
                                                                           ~~~~  ~~~~ ^
<source>:35:42: note: in instantiation of function template specialization 'make_2d_array<0,1,2,3,4,5>' requested here
    std::array<std::array<X,std::make_index_sequence<N>{});
                                         ^
1 error generated.
Compiler returned: 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)...
    };
}

是的,这有点可怕。原则很简单,我们需要在语法上将 XIsYIs 分开,以便每个 ... 扩展只解包其中一个,我们需要两个扩展来做“产品”而不是“压缩”。