如何使用编译时索引参数迭代参数包的大小
How to iterate over the size of a parameter pack with a compile-time index parameter
我正在尝试编写一个可变参数模板函数,其中包含一个循环,该循环遍历参数包中的每种类型。我正在使用它来构建一个元组,然后我在确定模板类型的回调函数上 apply
。
我想我可以使用 sizeof...(Args)
来做到这一点,如下所示:
template <typename ...Args>
void addCallback(void* handle, std::string address, std::function<void(Args...)> callback)
{
return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
std::tuple<Args...> args;
for (size_t i = 0; i < sizeof...(Args); i++)
{
std::get<i>(args) = message.getArg<std::tuple_element_t<i, decltype(args)>(i);
}
std::apply(callback, std::move(args));
});
}
这不会编译,因为 std::get<i>(args)
需要 i
作为编译时常量。但是,所有信息在编译时都是可用的。有没有办法使这项工作?我考虑过使用折叠表达式,但是
我正在使用 C++17。
可以定义辅助函数,使用index_sequence
展开Tuple
的元素,通过折叠表达式.
赋值
template<class Tuple, class Message, std::size_t... Is>
void assign_tuple(Tuple& tuple, const Message& message, std::index_sequence<Is...>) {
((std::get<Is>(tuple) = message.getArg<std::tuple_element_t<Is, Tuple>(Is)), ...);
};
template <typename ...Args>
auto addCallback(void* handle, std::string address, std::function<void(Args...)> callback) {
return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
std::tuple<Args...> args;
assign_tuple(args, message, std::make_index_sequence<sizeof...(Args)>{});
std::apply(callback, std::move(args));
});
}
在 C++20 中,您只需在函数内定义模板 lambda 即可。
我正在尝试编写一个可变参数模板函数,其中包含一个循环,该循环遍历参数包中的每种类型。我正在使用它来构建一个元组,然后我在确定模板类型的回调函数上 apply
。
我想我可以使用 sizeof...(Args)
来做到这一点,如下所示:
template <typename ...Args>
void addCallback(void* handle, std::string address, std::function<void(Args...)> callback)
{
return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
std::tuple<Args...> args;
for (size_t i = 0; i < sizeof...(Args); i++)
{
std::get<i>(args) = message.getArg<std::tuple_element_t<i, decltype(args)>(i);
}
std::apply(callback, std::move(args));
});
}
这不会编译,因为 std::get<i>(args)
需要 i
作为编译时常量。但是,所有信息在编译时都是可用的。有没有办法使这项工作?我考虑过使用折叠表达式,但是
我正在使用 C++17。
可以定义辅助函数,使用index_sequence
展开Tuple
的元素,通过折叠表达式.
template<class Tuple, class Message, std::size_t... Is>
void assign_tuple(Tuple& tuple, const Message& message, std::index_sequence<Is...>) {
((std::get<Is>(tuple) = message.getArg<std::tuple_element_t<Is, Tuple>(Is)), ...);
};
template <typename ...Args>
auto addCallback(void* handle, std::string address, std::function<void(Args...)> callback) {
return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
std::tuple<Args...> args;
assign_tuple(args, message, std::make_index_sequence<sizeof...(Args)>{});
std::apply(callback, std::move(args));
});
}
在 C++20 中,您只需在函数内定义模板 lambda 即可。