我不知道这个模式的名称,即使它存在。我需要一个函数来返回一组将在另一个函数中使用的参数。例如,我有这个功能:
void foo(int a, float b, some_class c);
我想写一个这样的函数:
//Theoretical code:
arguments get_arguments(){
return arguments(0,0.0f, some_class());
}
然后像这样打电话给foo
:
foo(get_arguments());
这可能吗?如果有,怎么样?
答案 0 :(得分:9)
可以通过使用std::tuple
并重载foo
函数来获取元组并将其展开以调用实际的foo
函数来完成。
答案 1 :(得分:7)
如果您的编译器支持将来添加C ++ 17,您可以通过修改get_arguments()
以返回std::tuple
并使用std::apply
来执行此操作:
std::apply(foo, get_arguments())
答案 2 :(得分:6)
get_arguments
可以使用std::make_tuple
实现:
auto get_arguments(){
return std::make_tuple(0,0.0f, some_class());
}
这将返回std::tuple<int,float,some_class>
。
您可以使用来自C ++ 17的foo
的参数调用std::experimental::apply
:
std::experimental::apply(foo, get_arguments());
如果您需要,可以std::experimental::apply
here实施。
要清理呼叫,您可以添加转发功能:
template <typename Tuple>
void foo(Tuple&& t) {
return std::experimental::apply(
static_cast<void(*)(int,float,some_class)>(&foo),
std::forward<Tuple>(t));
}
然后你可以使用你想要的语法:
foo(get_arguments());
答案 3 :(得分:2)
使用元组的示例代码,正如我现在看到的那样,它基于这个问题中的其他想法:
#include <iostream>
#include <tuple>
struct some_class{};
void foo(int a, float b, some_class c) {
std::cout << a << " " << b << "\n";
}
decltype(auto) get_arguments() {
return std::make_tuple(0.1f, 0.2f, some_class{});
}
template<typename T>
void callFoo(const T& args)
{
foo(std::get<0>(args), std::get<1>(args), std::get<2>(args));
}
int main()
{
callFoo(get_arguments());
}
答案 4 :(得分:2)
不完全是你问的......但是......只是为了好玩...使用std::bind
和std::ref
,您可以使用绑定的foo()
来呼叫bar()
,就这样
#include <tuple>
#include <complex>
#include <iostream>
#include <functional>
void foo(int a, float b, std::complex<double> c)
{ std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl; }
std::tuple<int, float, std::complex<double>> getArgs1 ()
{ return std::make_tuple(1, 22.22f, std::complex<double>{333.333, 4444.4444}); }
std::tuple<int, float, std::complex<double>> getArgs2 ()
{ return std::make_tuple(4444, 333.333f, std::complex<double>{22.22, 1.1}); }
int main()
{
std::tuple<int, float, std::complex<double>> t;
auto bar = std::bind(foo,
std::ref(std::get<0>(t)),
std::ref(std::get<1>(t)),
std::ref(std::get<2>(t)));
t = getArgs1();
bar();
t = getArgs2();
bar();
return 0;
}
输出
a = 1, b = 22.22, c = (333.333,4444.44)
a = 4444, b = 333.333, c = (22.22,1.1)
我再说一遍:只是为了好玩。
答案 5 :(得分:2)
std::tuple
允许您将调用foo
所需的参数打包在一起。正如其他人已经指出的那样,有几种方法可以调用你的函数,其中一些可能需要更新的标准。
在C ++ 11中,您已经拥有std::bind
,在您的情况下可以满足您的需求。以下是如何实现这一目标的示例:
#include <iostream>
#include <functional>
#include <tuple>
class MyClass {};
std::tuple<int, float, MyClass> get_arguments()
{
int a = 0;
float b = 1.0f;
MyClass c;
// ... calculate parameters;
return std::make_tuple(a, b, c);
}
void foo(int a, float b, MyClass c)
{
std::cout << "a: " << a << ", b: " << b << "\n";
}
int main(int argc, char* argv[])
{
// get tuple holding arguments
auto arguments = get_arguments();
// Binding arguments and calling directly
std::bind(
foo,
std::get<0>(arguments),
std::get<1>(arguments),
std::get<2>(arguments))();
return 0;
}
您可以将std::bind
调用放入包装器中,尤其是当您经常使用它时。
如果最终来回传递参数包,将它们封装到自己的数据类型甚至函数对象中可能是有意义的。此方法不需要std::tuple
也不需要std::bind
,因此即使您无法访问C ++ 11也可以使用此方法。
#include <iostream>
class MyClass {};
void foo(int a, float b, MyClass c)
{
std::cout << "a: " << a << ", b: " << b << "\n";
}
class FooCaller
{
public:
void operator()(void) const
{
foo(a, b, c);
}
int a;
float b;
MyClass c;
};
void get_arguments(FooCaller& fooCaller)
{
// ... calculate parameters;
fooCaller.a = 0.0f;
fooCaller.b = 1.0f;
}
int main(int argc, char* argv[])
{
// Create Instance and calculate/retrieve arguments
FooCaller fooCaller;
get_arguments(fooCaller);
// call 'foo'
fooCaller();
return 0;
}
这可以更通用,但这可能需要在C ++ 11及更高版本中引入一些模板元编程功能。
答案 6 :(得分:1)
实现相同目标的多种方式
将函数的返回类型声明为&#34; auto&#34;的最佳方法