Practical common solutions include:
Use the Optional_ class for the argument, for example boost::optional or the DIY equivalent.
What is the default value (and use the name in shell function definitions).
Overload each wrapper function as shown in the question.
Just repeat the default value in the definitions of shell functions, but this violates the DRY principle, do not repeat yourself.
Toby commented on the else-thread comment as an example of an asdf shell defined as
int asdf(int x=42,int y=42){ return foo(x)+foo(y);}
Using the Optional_ class:
auto foo( Optional_<int> x) -> int { return (x.is_empty()? 42 : x.value()); } auto asdf( Optional_<int> x = {}, Optional_<int> y = {} ) -> int { return foo( x ) + foo( y ); }
Using a named default:
int const foo_default = 42; auto foo( int x = foo_default ) -> int { return x; } auto asdf( int x = foo_default, int y = foo_default ) -> int { return foo( x ) + foo( y ); }
Using overloads:
auto foo( int x = 42 ) -> int { return x; } auto asdf() -> int { return foo() + foo(); } auto asdf( int x ) -> int { return foo( x ) + foo(); } auto asdf( int x, int y ) -> int { return foo( x ) + foo( y ); }
It is worth noting that asdf cannot be easily defined as a function template that forwards its arguments. In addition, such a template cannot be easily defined in a separate translation unit, and its address is not possible. For these reasons, I did not include this possible solution in the bullet list: it is very limited, not a general solution.
source share