使用std::index_sequence对std::数组初始化进行包扩展



我需要初始化一个std:数组,其中N个对象采用相同的构造函数参数,如std::vector<T>(size_t, {args...})中所示。从我在这里的搜索中,我发现了这个,它很有效:

template<typename T, size_t... Ints, typename... Args>
std::array<T, sizeof...(Ints)> make_array_(std::index_sequence<Ints...>, Args&&... args) {
return { (Ints, T{args...})... };
}
template<typename T, size_t N, typename... Args>
std::array<T, N> make_array(Args&&... args) {
return make_array_<T>(std::make_index_sequence<N>(), args...);
}
struct AStruct {
AStruct(int a, float b) : a_{ a }, b_{ b } {}
private:
int a_; float b_;
}
int main() {
auto anArray = make_array<AStruct, 10>(8, 5.4f);
// etc...
}

但我不懂第三行。(Ints, T{args...})...如何翻译成T{args...}, T{args...}, T{args...}...N次?

外部参数包没有按照您编写的方式进行扩展,它是这样扩展的(内部包没有显示为扩展的,因为您似乎对此没有问题(:

return { (0, T{args...}), (1, T{args...}), (2, T{args}) };

其中整数的类型为CCD_ 4。

(0, T{args...})是包含大括号的初始值设定项的一个元素。它是一个使用逗号运算符的表达式。逗号运算符首先计算左侧(0(,然后计算右侧(T{args...}(,返回后者。

由于0的评估没有副作用,并且其值被逗号运算符丢弃,因此这实际上等同于

return { T{args...}, T{args...}, T{args...} };

对此有一个警告。逗号运算符可以重载。如果有一个重载接受std::size_t作为第一个参数,T作为第二个参数,那么这将以一种意想不到的方式发生,而是用重载的结果初始化返回值。这可以通过将整数强制转换为void(它永远不会作为重载运算符调用的参数出现(来防止:

return { (void(Ints), T{args...})... };

最新更新