问题描述
是否可以初始化一个对象数组,该数组的成员是从另一个普通对象的 constexpr 数组初始化的。例如我有以下
struct X
{
X(int y): _x(y){}
int _x;
};
struct Z
{
static constexpr std::array<int,4> arr = {1,6,4};
// How does one implement make_array below that constructs
// X[0] from arr[0],X[1] from arr[1],etc.
// Is it even feasible in C++14/17?
std::array<X,arr.size()> xArr = make_array( );
};
解决方法
使用std::index_sequence
:
template <typename T,typename U,std::size_t N,std::size_t ... Is>
constexpr std::array<T,N> make_array(const std::array<U,N>& a,std::index_sequence<Is...>)
{
return {{T(a[Is])...}};
}
template <typename T,std::size_t N>
constexpr std::array<T,N>& a)
{
return make_array<T>(a,std::make_index_sequence<N>());
}
用法:
static constexpr std::array<int,4> arr = {1,6,4};
/*constexpr*/ std::array<X,arr.size()> xArr = make_array<X>(arr);
,
一种解决方案是使用参数包并对其进行扩展以构造数组的初始化列表。
我使用 std::index_sequence
和 std::make_index_sequence
来构造一个参数包,其中包含元素的索引(简单地 0、1、2、...、N-1)然后我解压这些索引进入初始化列表:
#include <array>
#include <utility>
// O : output type; type to convert elements to
// T : input type
// N : number of elements
// I : parameter pack of indexes
template<class O,class T,std::size_t ... I>
auto make_array_impl(const std::array<T,N> & p_input,std::index_sequence<I...>) -> std::array<O,N>
{
// Unpack the parameter pack into an initializer list
// Constructs an `O` from each element in order
return {O{p_input[I]}...};
}
// O : output type; type to convert elements to
// T : input type
// N : number of elements
template<class O,std::size_t N>
auto make_array(const std::array<T,N> & p_input)
{
// Helper function to automatically generate the parameter pack
return make_array_impl<O>(p_input,std::make_index_sequence<N>{});
}