从 2018 年开始编辑:在 C++17 中,这个问题的答案是不同的。您仍然必须将参数存储在::std::tuple 中,但是当调用函数::std::apply 时,它会处理解包此元组并为您调用该函数。如果您需要将索引技巧用于 ::std::apply 以外的其他用途,您应该研究一下 ::std::integer_sequence 和相关的辅助函数 ::std::make_index_sequence。
现在回到 2013 年的 C++11/14 答案。
您必须使用::std::tuple<Args...> 来存储它。但接下来的问题是如何在需要时打开它。为此,您需要使用一种称为“索引”的技术。
所以,这里有一个链接,指向我已经完成了您想要做的事情的地方。这里最相关的核心类是suspended_call。
https://bitbucket.org/omnifarious/sparkles/src/tip/sparkles/deferred.hpp?at=default
稍后,我将提取最相关的部分并将它们放在您的代码中。
This line:
auto saved_args = ::std::make_tuple(::std::move(args)...);
将参数保存到元组中。我在那里使用了::std::move,我认为这是正确的做法。但有可能我错了,我应该使用::std::forward。除了信号意图之外,我一直不清楚确切的区别。
使用保存的参数实际执行调用的代码可以在here 中找到。现在该代码完全针对我正在做的事情。实现索引技巧的位包括创建一组整数,这些整数映射到索引以用作::std::get<I> 模板的参数。一旦你有了这组整数,你就可以使用它来扩展对::std::get的调用,以获取所有元组元素作为单独的参数。
我将尝试以相对简单的方式编写代码:
#include <tuple>
#include <cstddef>
#include <string>
#include <utility>
template < ::std::size_t... Indices>
struct indices {};
template < ::std::size_t N, ::std::size_t... Is>
struct build_indices : build_indices<N-1, N-1, Is...>
{};
template < ::std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...>
{};
template <typename FuncT, typename ArgTuple, ::std::size_t... Indices>
auto call(const FuncT &f, ArgTuple &&args, const indices<Indices...> &)
-> decltype(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...))
{
return ::std::move(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...));
}
template <typename FuncT, typename ArgTuple>
auto call(const FuncT &f, ArgTuple &&args)
-> decltype(call(f, args,
build_indices< ::std::tuple_size<ArgTuple>::value>{}))
{
const build_indices< ::std::tuple_size<ArgTuple>::value> indices;
return ::std::move(call(f, ::std::move(args), indices));
}
int myfunc(::std::string name, const unsigned int foo)
{
return 0;
}
int foo(::std::tuple< ::std::string, const unsigned int> saved_args)
{
return call(myfunc, ::std::move(saved_args));
}
很多代码都是从this page on the indices trick借来的。
另外,这是一个样本,您必须根据自己的具体情况稍作调整。基本上,只需在某处致电call(nestFunc, saved_args)。