C++11:我可以从多个 args 转到 tuple,但我可以从 tuple 转到多个 args 吗? [复制]
Posted
技术标签:
【中文标题】C++11:我可以从多个 args 转到 tuple,但我可以从 tuple 转到多个 args 吗? [复制]【英文标题】:C++11: I can go from multiple args to tuple, but can I go from tuple to multiple args? [duplicate] 【发布时间】:2012-06-01 17:26:19 【问题描述】:可能重复:How do I expand a tuple into variadic template function's arguments?“unpacking” a tuple to call a matching function pointer
在 C++11 模板中,有没有办法使用元组作为(可能是模板)函数的单独参数?
示例: 假设我有这个功能:
void foo(int a, int b)
我有元组auto bar = std::make_tuple(1, 2)
。
我可以用它以模板方式调用foo(1, 2)
吗?
我的意思不是简单的foo(std::get<0>(bar), std::get<1>(bar))
,因为我想在不知道参数数量的模板中执行此操作。
更完整的例子:
template<typename Func, typename... Args>
void caller(Func func, Args... args)
auto argtuple = std::make_tuple(args...);
do_stuff_with_tuple(argtuple);
func(insert_magic_here(argtuple)); // <-- this is the hard part
我应该注意,我不想创建一个适用于一个 arg 的模板,另一个适用于两个 arg 的模板,等等……
【问题讨论】:
当然。你想要像template <typename F, typename Tuple, int N...> call(F f, Tuple const & t) f(std::get<N>(t)...);
这样的东西。现在只需填写空白:-)
您的意思是跳过可变参数模板并改为创建多个caller()
模板吗?
@Thomas:你必须制作一个小调度工具来构建整数包N...
,并在N == std::tuple_size<Tuple>::value
时部分专门化,你想以我的方式调用原始函数建议。
(当然应该是int ...N
。)
【参考方案1】:
试试这样的:
// implementation details, users never invoke these directly
namespace detail
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
static void call(F f, Tuple && t)
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
;
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
static void call(F f, Tuple && t)
f(std::get<N>(std::forward<Tuple>(t))...);
;
// user invokes this
template <typename F, typename Tuple>
void call(F f, Tuple && t)
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
例子:
#include <cstdio>
int main()
auto t = std::make_tuple("%d, %d, %d\n", 1,2,3);
call(std::printf, t);
通过一些额外的魔法并使用std::result_of
,您可能还可以使整个事物返回正确的返回值。
【讨论】:
@JonathanWakely :call_impl
是一个实现细节——用户从不直接调用它,全局call
是用户交互的全部。这个例子不清楚吗?
啊,不,我只是没看清楚,我认为 call
是 OP 的 caller
的替代品,所以 call_impl
的笨拙使用发生在用户的代码中。跨度>
我的好先生,这令人困惑,值得一票。
这是我在 *** 上找到的最好的解压 std::tuple 的方法,而且它有一半的投票支持更糟糕的解决方案......
只是一个建议,您可能想在其中抛出一个auto
进行调用,这样您也可以使用函数的返回值,顺便说一句,除此之外真的很喜欢解决方案【参考方案2】:
创建一个“索引元组”(编译时整数的元组),然后转发到另一个函数,该函数将索引作为参数包推导出来,并在包扩展中使用它们来调用元组上的std::get
:
#include <redi/index_tuple.h>
template<typename Func, typename Tuple, unsigned... I>
void caller_impl(Func func, Tuple&& t, redi::index_tuple<I...>)
func(std::get<I>(t)...);
template<typename Func, typename... Args>
void caller(Func func, Args... args)
auto argtuple = std::make_tuple(args...);
do_stuff_with_tuple(argtuple);
typedef redi::to_index_tuple<Args...> indices;
caller_impl(func, argtuple, indices());
我对@987654326@ 的实现位于https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h
但它依赖于模板别名,因此如果您的编译器不支持您需要修改它以使用 C++03 样式的“模板类型定义”并将caller
的最后两行替换为
typedef typename redi::make_index_tuple<sizeof...(Args)>::type indices;
caller_impl(func, argtuple, indices());
类似的实用程序在 C++14 中被标准化为 std::index_sequence
(有关独立的 C++11 实现,请参见 index_seq.h)。
【讨论】:
你能解释一下type::template
的语法吗?
@ubik womble.decadent.org.uk/c++/template-faq.html#disambiguation
@JonathanWakely 非常好。也许我错过了一个明显的技巧,但是当有问题的函数是构造函数时,有什么方法可以像这样应用tuple
......还是要求有点太多的魔法? :D
嗯,我想我已经通过在 T_ReturnedObject
上模板化 _impl
等效函数并让它调用该对象的 ctor 并解包所有内容来使其工作。我想这就是我提到的“明显的把戏”!
@underscore_d,是的,这是显而易见的方法。以上是关于C++11:我可以从多个 args 转到 tuple,但我可以从 tuple 转到多个 args 吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何从 UITableViewController 转到多个视图控制器