通过单个函数返回另一个函数的多个参数
Return several arguments for another function by a single function
这个问题被关闭为完全重复,因为我选择了一个误导性的问题标题。这并没有错,但提出了一个经常讨论的问题,例如在这个问题上。由于内容是关于Stackoverflow上从未涉及的更具体的主题,我希望重新打开这个问题。现在发生了这种情况,所以问题来了。
我给出了一个函数,期望三个整数值作为参数length(int x, int y, int z);
。我无法修改此函数,例如接受任何结构或元组作为单个参数。
C++有没有办法编写另一个函数,该函数可以用作上述函数的单个参数,例如length(arguments());
?
无论如何,该函数arguments();
返回类型似乎需要int, int, int
。但据我所知,我无法在C++中定义和使用这样的函数。我知道我可以按arguments()
返回列表、元组、结构或类。这个问题已经结束了,因为有些人认为我会问这个问题。但困难的部分是传递元组、结构或任何作为三个给定整数参数的内容。
是否可能,如果是,这在C++中怎么可能?使用 C++11 的解决方案会很好。
直接的方法可以做你想做的事情,但这里有一种 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()
被更改,因此它返回一个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
的函数创建另一个实现。
再次抱歉过早关闭您的问题。
附言。您需要添加以下包含语句来测试这一点:
#include <tuple>
#include <type_traits>
#include <iostream>
这是不可能的,C++不允许原生提供 3 个返回值,这些值可以用作另一个函数的 3 个单独的输入参数。
但是有一些"技巧"可以返回多个值。尽管这些都没有为您的问题提供完美的解决方案,因为它们无法用作单个参数来length()
而不修改length()
。
使用容器对象,如struct
、tuple
或class
typedef struct { int a,b,c; } myContainer;
myContainer arguments(int x, int y, int z) {
myContainer result;
result.a = 1;
// etc
return result;
}
myContainer c = arguments(x, y, z);
length(c.a, c.b, c.c);
诀窍是重载length()
函数,因此看起来您可以将其与单个参数一起使用:
void length(myContainer c) {
length(c.a, c.b, c.c);
}
length(arguments());
当然,你可以通过使用inline
、宏等来进一步优化它。
我知道这仍然不是你想要的,但我认为这是最接近的方法。
声明一个struct { int a, b, c; }
或类似的东西(一个类也可以工作( - 我认为你一直在编程python或php或类似的东西。
大多数编程语言都会通过某种形式的适配器函数来做到这一点。这是一个函数,它将调用的函数(此处length
(和调用它的参数作为参数。您可能可以使用模板在C++中构建类似的东西。查看functional
标题以获得灵感。
一种原生提供您正在寻找的语言是 Perl。你可以写:
sub arguments {
return 1, 2, 3;
}
sub length {
my ($p1, $p2, $p3) = @_;
# … Work with $p1, $p2 and $p3
}
length(arguments());
通过引用传入参数,以便您可以在不返回或返回结构的情况下更改它们。只能从函数返回单个值。
我们只能返回一个值。 但是如果你想返回多个值,你可以使用数组或定义一个对象或结构
int* arguments() {
int x[1,4,6]
return x;
};
void length(int i[]);
length(arguments());
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数