I do not know the name of this pattern or even if it is exist. I need a function that return a set of arguments that would be used in another function. For example, I have this function:
void foo(int a, float b, some_class c);
I want to write a function like this:
//Theoretical code:
arguments get_arguments(){
return arguments(0,0.0f, some_class());
}
Then call foo
like this:
foo(get_arguments());
Is this possible? if yes,How?
There are two ways to pass arguments to a function: by reference or by value. Modifying an argument that's passed by reference is reflected globally, but modifying an argument that's passed by value is reflected only inside the function.
Arguments are Passed by Value The parameters, in a function call, are the function's arguments. JavaScript arguments are passed by value: The function only gets to know the values, not the argument's locations. If a function changes an argument's value, it does not change the parameter's original value.
Default values indicate that the function argument will take that value if no argument value is passed during the function call. The default value is assigned by using the assignment(=) operator of the form keywordname=value.
You can access specific arguments by calling their index. var add = function (num1, num2) { // returns the value of `num1` console.
It could probably be done by using std::tuple
and overloading the foo
function to take a tuple and expand it to call the actual foo
function.
If your compiler supports future C++17 addition, you can do this by modifying get_arguments()
to return std::tuple
and using std::apply
:
std::apply(foo, get_arguments())
get_arguments
can be implemented with std::make_tuple
:
auto get_arguments(){
return std::make_tuple(0,0.0f, some_class());
}
This will return a std::tuple<int,float,some_class>
.
You can call foo
with the arguments using std::experimental::apply
from C++17:
std::experimental::apply(foo, get_arguments());
Live Demo
There is an implementation of std::experimental::apply
here if you need one.
To clean up the call, you could add a forwarding function:
template <typename Tuple>
void foo(Tuple&& t) {
return std::experimental::apply(
static_cast<void(*)(int,float,some_class)>(&foo),
std::forward<Tuple>(t));
}
Then you can use the syntax you desire:
foo(get_arguments());
Live Demo
Sample code using tuple, as I see now it bases on other ideas from this question:
[live]
#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());
}
Not exactly what you ask... but... just for fun... using std::bind
and std::ref
, you can call foo()
using a binded bar()
, in this way
#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;
}
The output is
a = 1, b = 22.22, c = (333.333,4444.44)
a = 4444, b = 333.333, c = (22.22,1.1)
I repeat: just for fun.
std::tuple
allows you to pack together the arguments you need for your call to foo
. As others already pointed out, there are several ways you can then call your function and some of these might require a more recent standard.
In C++11, you already have std::bind
which should suit your needs just fine in your case. Here's an example of how this could be achieved:
#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;
}
You can put the std::bind
call into a wrapper, especially when you're using it frequently.
If you end up passing around packs of parameters back and forth, it might make sense to encapsulate them into their own data type or even a function object. This method does not need std::tuple
nor std::bind
and can thus be used even when you don't have access to 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;
}
This could be made more generic but this might require some template metaprogramming features introduced in C++11 and later.
Multiple ways to achieve the same things
The best way to declare return type of function as "auto"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With