At times, C ++ wants a more flexible mechanism for parameterizing functions. For example, we have a function with two required parameters and a large number of optional ones.
bool foo(int important, int& pOut, int sometimes = 1, int occasionally = 2, int rarely = 3) {
The problems here may be the following.
- Users constantly confuse the order of parameters, their type is almost completely the same, so the compiler can not help with anything (except sometimes with the second parameter).
- Of the optional parameters, most often one is needed, and if it is not sometimes , users are forced to recall the default values in order to set them explicitly in the call. The default values are different, so there are a lot of errors again.
- There is no way to express the dependence of the default values of some parameters on others.
')
These problems can be solved in different ways: transfer structure as a parameter, use function overloading or even functions with different names ... Boost offers another solution.
These are
named parameters . We are no longer tied to the order of the parameters, the ability to specify conscious names when calling, significantly reduces the likelihood of errors. As an additional bonus, we get the ability to use some parameters when calculating the default values of others.
As an example, consider how you can define the function
foo using the proposed mechanism (change the name to
namedParametersFoo so that there is no confusion). First, we include the header header file and define the parameter names using a special macro. Pay attention - no punctuation.
#include <boost/parameter.hpp> BOOST_PARAMETER_NAME(important) BOOST_PARAMETER_NAME(pOut) BOOST_PARAMETER_NAME(sometimes) BOOST_PARAMETER_NAME(occasionally) BOOST_PARAMETER_NAME(rarely)
further set the function
BOOST_PARAMETER_FUNCTION( (bool), namedParametersFoo, tag, (required (important, *) (in_out(pOut), *) ) (optional (sometimes, *, important * 2) (occasionally, *, 300) (rarely, *, 400) ) ) {
Four parameters are passed to the macro, separated by commas.
- Type of return value - necessarily in brackets
- Function name
- Namespace with parameters. BOOST_PARAMETER_NAME automatically puts ads in the tag
- Parameter list
The parameter list has its own structure. Also, note that there are practically no punctuation marks - there are only commas when defining immediate parameters.
First comes the
required block. As the name suggests, it contains a list of required parameters. Each parameter must be placed in parentheses. To define a required parameter, you must specify its name and type restrictions. This article does not consider the type restriction mechanism, so we will simply use an asterisk. More on this topic can be read
here .
This is followed by a block of optional parameters. Here, when defining each parameter, there is an additional opportunity to set a default value. As can be seen from the example above, the remaining parameters can be used in expressions.
Actually everything. The function supports calls "in the old manner" - as if it were defined with the usual optional parameters. Those. as if earned an option
bool newFoo(int important, int& pOut, int sometimes = important * 2, int occasionally = 2, int rarely = 3) {
newFoo will not compile due to the sometimes dependent parameterThose. you can use
namedParametersFoo so
int s = 0; namedParametersFoo(1, s, 1, 1, 1); namedParametersFoo(1, s, 1, 1); namedParametersFoo(1, s, 1); namedParametersFoo(1, s);
But that is not all! By using named parameters, we free ourselves from both the order of the arguments and the unnecessary unnecessary defaults. The only inconvenience is the need to add an underscore at the beginning of the names.
namedParametersFoo(_sometimes = 1, _important = 111, _pOut = s);
So, what in this example is the new good
- Visibility - it is clear what we mean by numbers 1 and 111, the probability of getting confused / wrong is reduced
- Arbitrary order - the optional parameter is written first, and everything works
Despite the fact that it has become possible to change the position of the required parameters and even mix them with optional ones, everything continues to be controlled at the compilation stage, i.e. next code
namedParametersFoo(_sometimes = 1, _pOut = s);
fails - missing
_important required parameter
That's all. I would like to add that the mechanism is not the easiest and most obvious, so if it turns out to get around the problem with standard language tools, then it is better to do so. In addition, the use of named boost parameters can adversely affect compile time. But if all the workarounds are obtained by curves, and the boost is already used in the project, there will definitely be a benefit.