Skip some arguments in a C++ function?
I have a C++ function that has 5 arguments, all of which have default values. If I pass in the first three arguments, the program will assign a default value to the last two arguments. Is there any way to pass 3 arguments, and skip one in the middle, giving values to say, the first, second, and fifth arguments?
Solution 1:
Not directly, but you might be able to do something with std::bind:
int func(int arg1 = 0, int arg2 = 0, int arg3 = 0);
// elsewhere...
using std::bind;
using std::placeholders::_1;
auto f = bind(func, 0, _1, 0);
int result = f(3); // Call func(0, 3, 0);
The downside is of course that you are re-specifying the default parameters. I'm sure somebody else will come along with a more clever solution, but this could work if you're really desperate.
Solution 2:
With a classical 5 arguments function, there is no way to give it only 3 or 4. You can only write 3 or 4 with default arguments but at the end you will get a function call with 5 arguments.
There are also issues with you system if there are several parameters with the same type.
For instance, if you have foo(int a=4,int b=5)
and call foo(10)
, how do you know you want to call foo(10,5)
or foo(4,10)
?
With C++11 tuples and Named parameters idiom, you can cheat it a little bit.
#include <iostream>
#include <functional>
#include <tuple>
#include <string>
struct f_
{
private:
typedef std::tuple<int,int,double> Args;
//default arguments
static constexpr const Args defaults = std::make_tuple(10,52,0.5);
Args args;
public :
f_():args(defaults)
{}
template <int n,class T> f_& setArg(T&& t)
{
std::get<n>(args) = t;
return *this;
}
void operator()()
{
return (*this)(std::move(args));
}
void operator()(Args&& a)
{
int n1=std::get<0>(a);
int n2=std::get<1>(a);
double n3=std::get<2>(a);
std::cout<<n1<<" "<<n2<<" "<<n3<<std::endl;
}
};
#define set(n,v) setArg<n>((v))
int main()
{
//f_().set<1>(42).set<3>("foo") ();
f_().setArg<1>(42)(); //without Macro
f_().set(0,666).set(1,42)(); //with Macro
f_()(); //without any parameters
f_()(std::forward_as_tuple(-21,-100,3.14)); //direct call
}
An alternative method is to use std::bind as described there