通过单个函数返回另一个函数的多个参数 [英] Return several arguments for another function by a single function
问题描述
由于我选择了一个误导性的问题标题,因此该问题已完全重复关闭.这没有错,但提出了一个经常讨论的问题,例如在这个问题中.由于内容是关于 Stackoverflow 上从未涉及的更具体的主题,我希望重新打开这个问题.这已经发生了,所以问题来了.
This question was closed as exact duplicate since I chose a misleading question title. It was not wrong but suggested an issue often discussed, e.g. in this question. Since the content is about a more specific topic never covered on Stackoverflow I would like the question to be reopened. This happened now, so here goes the question.
我给出了一个需要三个整数值作为参数的函数length(int x, int y, int z);
.我无法修改此功能,例如接受任何结构或元组作为单个参数.
I have given a function expecting three integer values as parameters length(int x, int y, int z);
. I cannot modify this function, e.g. to accept a struct or tuple of whatever as single parameter.
在 C++ 中有没有办法编写另一个可以用作上述函数的单个参数的函数,例如 length(arguments());
?
Is there a way in C++ to write another function which can be used as single argument to the function above, like length(arguments());
?
无论如何,该函数 arguments();
的返回类型似乎需要是 int, int, int
.但据我所知,我无法在 C++ 中定义和使用这样的函数.我知道我可以通过 arguments()
返回一个列表、一个元组、一个结构体或一个类.这个问题已经结束,因为有些人认为我会问这个问题.但困难的部分是传递元组、结构体或其他三个给定的整数参数.
Anyhow the return type of that function arguments();
seems to need to be int, int, int
. But as far as far as I know I can't define and use functions like this in C++. I know that I could return a list, a tuple, a struct or a class by arguments()
. The question was closed because some people thought I would have asked about this. But the difficult part is to pass the tuple, or struct, or whatever as the three given integer parameters.
这可能吗,如果是,在 C++ 中怎么可能?使用 C++11 的解决方案会很好.
Is this possible and if yes, how is that possible in C++? A solution making use of C++11 would be fine.
推荐答案
我不认为有任何直接的方法可以做你想做的事,但这里有一个 C++11 技术,我在我的几个地方使用了它代码.基本思想是使用我称为 call_on_tuple
的模板函数来获取函数参数 f
以及进一步参数的元组,展开元组并调用扩展参数列表上的函数:
I don't think there is any direct way of doing what you want, but here is a C++11 technique that I use in several places of my code. The basic idea is to use a template function which I've called call_on_tuple
to take a function argument f
as well as a tuple of further arguments, expand the tuple and call the function on the expanded list of arguments:
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)...); }
所以这个想法是,而不是调用
So the idea is that instead of calling
length(arguments());
你会打电话
call_on_tuple(length,arguments());
这假设 arguments()
已更改,因此它返回 std::tuple<int,int,int>
(这基本上是您提出的问题的想法引用).
This assumes that arguments()
is changed so it returns a std::tuple<int,int,int>
(this is basically the idea from the question you cited).
现在困难的部分是如何获得 Is...
参数包,它是一个整数包 0,1,2,...
用于给元组的元素编号.
Now the difficult part is how to get the Is...
argument pack, which is a pack of integers 0,1,2,...
used to number the elements of the tuple.
如果你确定你总是有三个参数,你可以按字面意思使用 0,1,2
,但如果你的目标是让这个函数适用于任何 n 元函数,我们需要另一个技巧,已在其他帖子中进行了描述,例如在 这篇文章.
If you are sure you'll always have three arguments, you could use 0,1,2
literally, but if the ambition is to make this work for any n-ary function, we need another trick, which has been described by other posts, for example in several answers to this post.
将参数的数量,即 sizeof...(Args)
转换成一个 list 的整数 0,1,...,sizeof...(Args)
:
It's a trick to transform the number of arguments, i.e. sizeof...(Args)
into a list of integers 0,1,...,sizeof...(Args)
:
我将把这个技巧和 call_on_tuple
的实现放在一个命名空间 detail
中:
I'll put this trick and the implementation of call_on_tuple
in a namespace 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
在全局命名空间中定义如下:
Now the actual function call_on_tuple
is defined in global namespace like this:
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
.
It basically calls detail::index_maker
to generate the list of increasing integers and then calls detail::call_on_tuple
with that.
因此,您可以这样做:
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;
}
希望足够接近您所需要的.
which is hopefully close enough to what you needed.
注意.我还添加了一个 enable_if
以确保它仅用于实际返回值的函数 f
.您可以轻松地为返回 void
的函数创建另一个实现.
Note. I have also added an enable_if
to ensure this is only used with functions f
that actually return a value. You can readily make another implementation for functions that return void
.
再次抱歉过早结束您的问题.
Sorry again for closing your question prematurely.
附注.您需要添加以下包含语句来对此进行测试:
PS. You'll need to add the following include statements to test this:
#include <tuple>
#include <type_traits>
#include <iostream>
这篇关于通过单个函数返回另一个函数的多个参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!