通过单个函数返回另一个函数的几个参数

dan*_*jar 4 c++ syntax arguments function c++11

由于我选择了一个误导性的问题标题,因此这个问题被完全复制了.这没错,但建议经常讨论一个问题,例如在这个问题中.由于内容是关于Stackoverflow上从未涉及的更具体的主题,我希望重新打开该问题.现在发生了这种情况,所以这就是问题所在.

我给了一个期望三个整数值作为参数的函数length(int x, int y, int z);.我无法修改此函数,例如接受任何单个参数的结构或元组.

在C++中有没有办法编写另一个函数,可以作为上面函数的单个参数,比如length(arguments());

无论如何,该函数的返回类型arguments();似乎需要int, int, int.但据我所知,我无法在C++中定义和使用这样的函数.我知道我可以返回一个列表,一个元组,一个结构或一个类arguments().问题已经结束,因为有些人认为我会问这个问题.但困难的部分是传递元组,结构,或任何三个给定的整数参数.

这是可能的吗?如果是的话,这在C++中怎么可能?使用C++ 11的解决方案没问题.

jog*_*pan 8

我认为没有任何直接的方法可以做你想要的,但这里有一个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)...); }
Run Code Online (Sandbox Code Playgroud)

所以我的想法是不是打电话

length(arguments());
Run Code Online (Sandbox Code Playgroud)

你会打电话

call_on_tuple(length,arguments());
Run Code Online (Sandbox Code Playgroud)

这假设arguments()已经改变,所以它返回一个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)...); }
}
Run Code Online (Sandbox Code Playgroud)

现在实际的函数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());
}
Run Code Online (Sandbox Code Playgroud)

它基本上调用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;
}
Run Code Online (Sandbox Code Playgroud)

希望足够接近你需要的东西.

注意.我还添加了一个enable_if以确保它仅用于f实际返回值的函数.您可以轻松地为返回的函数创建另一个实现void.

再次抱歉提前结束您的问题.

PS.您需要添加以下include语句来测试它:

#include <tuple>
#include <type_traits>
#include <iostream>
Run Code Online (Sandbox Code Playgroud)