使用 std::index_sequence 为 std::array 初始化打包扩展
Pack expansion for std::array initialization using std::index_sequence
我需要用 N 个对象初始化一个 std:array,使用与 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}) };
其中整数的类型为 std::size_t
。
(0, T{args...})
是大括号括起来的初始值设定项的一个元素。它是一个使用逗号运算符的表达式。逗号运算符首先计算左侧 (0
),然后计算右侧 (T{args...}
),然后 return 计算后者。
因为 0
的计算没有副作用并且它的值被逗号运算符丢弃,这实际上等同于
return { T{args...}, T{args...}, T{args...} };
对此有一个警告。逗号运算符可以重载。如果有一个重载接受 std::size_t
作为第一个参数和 T
作为第二个参数,那么这将以意想不到的方式运行,用重载的结果初始化 return 值。这可以通过将整数转换为 void
来防止(它永远不会作为重载运算符调用的参数出现):
return { (void(Ints), T{args...})... };
我需要用 N 个对象初始化一个 std:array,使用与 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}) };
其中整数的类型为 std::size_t
。
(0, T{args...})
是大括号括起来的初始值设定项的一个元素。它是一个使用逗号运算符的表达式。逗号运算符首先计算左侧 (0
),然后计算右侧 (T{args...}
),然后 return 计算后者。
因为 0
的计算没有副作用并且它的值被逗号运算符丢弃,这实际上等同于
return { T{args...}, T{args...}, T{args...} };
对此有一个警告。逗号运算符可以重载。如果有一个重载接受 std::size_t
作为第一个参数和 T
作为第二个参数,那么这将以意想不到的方式运行,用重载的结果初始化 return 值。这可以通过将整数转换为 void
来防止(它永远不会作为重载运算符调用的参数出现):
return { (void(Ints), T{args...})... };