使用std :: index_sequence

时间:2019-10-24 07:09:14

标签: c++ templates index-sequence

我需要使用N个对象(与std::vector<T>(size_t, {args...})中相同的构造函数参数来初始化std:array。从我的搜索中,我想到了这个方法,

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次?

1 个答案:

答案 0 :(得分:3)

外部参数包没有以您编写的方式扩展,而是以这种方式扩展(内部包未显示为扩展,因为您似乎对此没有问题):

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

其中整数为std::size_t类型。

(0, T{args...})是用括号括起来的初始化程序的一个元素。它是使用逗号运算符的表达式。逗号运算符首先评估左侧(0),然后评估右侧(T{args...}),然后返回右侧。

因为对0的求值没有副作用,并且其值被逗号运算符丢弃,所以它实际上等效于

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

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

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