我认为没有任何直接的方法可以做你想做的事,但这是我在代码的几个地方使用的 C++11 技术。基本思想是使用我调用的模板函数call_on_tuple
来获取函数参数f
以及进一步参数的元组,扩展元组并在扩展的参数列表上调用函数:
template <typename Fun, typename... Args, unsigned... Is>
typename std::result_of<Fun(Args...)>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
{ return f(std::get<Is>(tup)...); }
所以这个想法是,而不是打电话
length(arguments());
你会打电话给
call_on_tuple(length,arguments());
这假设它arguments()
已更改,因此它返回 a std::tuple<int,int,int>
(这基本上是您引用的问题的想法)。
现在困难的部分是如何获取Is...
参数包,它是一个整数包,0,1,2,...
用于对元组的元素进行编号。
如果你确定你总是有三个参数,你可以0,1,2
按字面意思使用,但如果你的目标是让它适用于任何 n 元函数,我们需要另一个技巧,其他帖子已经描述了这个技巧,例如在几个这个帖子的答案。
将参数的数量sizeof...(Args)
转换为整数列表0,1,...,sizeof...(Args)
是一个技巧:
我将把这个技巧和实现call_on_tuple
放在一个命名空间中detail
:
namespace detail {
template <unsigned... Is>
struct indices
{ };
template <unsigned N, unsigned... Is>
struct index_maker : index_maker<N-1,N-1,Is...>
{ };
template <unsigned... Is>
struct index_maker<0,Is...>
{ typedef indices<Is...> type; };
template <typename Fun, typename... Args, unsigned... Is>
typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
typename std::result_of<Fun(Args...)>::type>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
{ return f(std::get<Is>(tup)...); }
}
现在实际函数call_on_tuple
在全局命名空间中定义如下:
template <typename Fun, typename... Args>
typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
typename std::result_of<Fun(Args...)>::type>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup)
{
using std::tuple;
using std::forward;
using detail::index_maker;
return detail::call_on_tuple
(forward<Fun>(f),forward<tuple<Args...>>(tup),typename index_maker<sizeof...(Args)>::type());
}
它基本上调用detail::index_maker
生成递增整数列表,然后调用detail::call_on_tuple
它。
因此,您可以这样做:
int length(int x, int y, int z)
{ return x + y + z; }
std::tuple<int,int,int> arguments()
{ return std::tuple<int,int,int> { 1 , 2 , 3 }; }
int main()
{
std::cout << call_on_tuple(length,arguments()) << std::endl;
return 0;
}
希望这与您需要的足够接近。
笔记。我还添加了一个enable_if
以确保仅与f
实际返回值的函数一起使用。您可以轻松地为返回的函数创建另一个实现void
。
再次抱歉过早地结束您的问题。
PS。您需要添加以下包含语句来测试它:
#include <tuple>
#include <type_traits>
#include <iostream>