Despite the fact that Boost.Parameters are funny, it suffers (unfortunately) for a number of problems, including a collision with a placeholder (and the need to debug fancy preprocessors / template errors):
BOOST_PARAMETER_NAME(p1)
Creates a placeholder _p1 , which you then use later. If you have two different headers declaring the same placeholder, you get a conflict. Not fun.
There is a much simpler (both conceptually and practically) answer based on the Builder Template, which is the Idiom Named Parameter .
Instead of specifying such a function:
void f(int a, int b, int c = 10, int d = 20);
You specify the structure on which you will override operator() :
- the constructor is used to request required arguments (not strictly in the Idiom of Named Parameters, but no one said you need to follow it blindly), and default values ββare set for optional
- each optional parameter is assigned a setter
As a rule, it is combined with Chaining, which means that setters return a link to the current object, so that calls can be chained on one line.
class f { public: // Take mandatory arguments, set default values f(int a, int b): _a(a), _b(b), _c(10), _d(20) {} // Define setters for optional arguments // Remember the Chaining idiom f& c(int v) { _c = v; return *this; } f& d(int v) { _d = v; return *this; } // Finally define the invocation function void operator()() const; private: int _a; int _b; int _c; int _d; }; // class f
Call:
f(1, 2).c(3)();
I saw an option, introducing the required arguments as parameters to operator() , this avoids arguments as attributes, but the syntax is a bit weirder:
f().c(3)(1, 2);
As soon as the compiler introduced all the calls to the constructor and setter (which is why they are defined here, but operator() not), it should lead to the same efficient code as compared to the βregularβ function call.