Named Parameters Boost
- Tutorial
At times, C ++ wants a more flexible function parameterization mechanism. For example, we have a function with two required parameters and a large number of optional.
The problems here may be as follows
These problems can be solved in different ways: pass a 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 added bonus, we get the opportunity 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 boost header file and determine the parameter names using a special macro. Pay attention - no punctuation marks.
next we set the function
Four parameters are passed to the macro, separated by commas
The list of parameters has its own structure. Also, note that there are almost no punctuation marks - there are only commas in determining the 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. In this article, the type restriction mechanism is not considered, so we will just use an asterisk. Read more on this topic here .
Then follows a block of optional parameters. Here, when defining each parameter, there is an additional opportunity to set the default value. As you can see from the example above, you can use other parameters in expressions.
Actually everything. The function supports calls "the old fashioned way" - as if it were defined with the usual optional parameters. Those. as if earned option
newFoo is not compiled due to the dependence of the sometimes parameter on important
i.e. can use namedParametersFoo so
But that is not all! By using the named parameters, we free ourselves from both the order of the arguments and the required unnecessary default values. The only inconvenience is that you need to add an underscore at the beginning of the names.
So what in this example is a new good
Despite the fact that it became possible to change the position of required parameters and even mix them with optional parameters, everything continues to be controlled at the compilation stage, i.e. following code
will not be collected - the necessary parameter _important is missed
That's all. I would like to add that the mechanism is not the simplest and most obvious, so if you can get around the problem by standard means of the language, then it is better to do so. In addition, using named boost parameters can adversely affect compilation time. But if all the workarounds are crooked, and boost is already being used in the project, then there will definitely be benefits.
boolfoo(int important, int& pOut, int sometimes = 1, int occasionally = 2, int rarely = 3){
//...
}
The problems here may be as follows
- Users constantly confuse the order of parameters, their type is almost identical, so the compiler can not help (except sometimes with the second parameter).
- Of the optional parameters, one is most often needed, and if it is not sometimes , users are forced to recall the default values 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: pass a 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 added bonus, we get the opportunity 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 boost header file and determine the parameter names using a special macro. Pay attention - no punctuation marks.
#include<boost/parameter.hpp>
BOOST_PARAMETER_NAME(important)
BOOST_PARAMETER_NAME(pOut)
BOOST_PARAMETER_NAME(sometimes)
BOOST_PARAMETER_NAME(occasionally)
BOOST_PARAMETER_NAME(rarely)
next we 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
- Return type - required in parentheses
- Function name
- Namespace with parameters. BOOST_PARAMETER_NAME automatically places ads in tag
- Parameter List
The list of parameters has its own structure. Also, note that there are almost no punctuation marks - there are only commas in determining the 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. In this article, the type restriction mechanism is not considered, so we will just use an asterisk. Read more on this topic here .
Then follows a block of optional parameters. Here, when defining each parameter, there is an additional opportunity to set the default value. As you can see from the example above, you can use other parameters in expressions.
Actually everything. The function supports calls "the old fashioned way" - as if it were defined with the usual optional parameters. Those. as if earned option
boolnewFoo(int important, int& pOut, int sometimes = important * 2, int occasionally = 2, int rarely = 3){
//...
}
newFoo is not compiled due to the dependence of the sometimes parameter on important
i.e. 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 the named parameters, we free ourselves from both the order of the arguments and the required unnecessary default values. The only inconvenience is that you need to add an underscore at the beginning of the names.
namedParametersFoo(_sometimes = 1, _important = 111, _pOut = s);
So what in this example is a new good
- Visibility - it is clear what exactly we mean by numbers 1 and 111, the probability of getting confused / mistaken decreases
- Arbitrary order - an optional parameter is written first, and everything works
Despite the fact that it became possible to change the position of required parameters and even mix them with optional parameters, everything continues to be controlled at the compilation stage, i.e. following code
namedParametersFoo(_sometimes = 1, _pOut = s);
will not be collected - the necessary parameter _important is missed
That's all. I would like to add that the mechanism is not the simplest and most obvious, so if you can get around the problem by standard means of the language, then it is better to do so. In addition, using named boost parameters can adversely affect compilation time. But if all the workarounds are crooked, and boost is already being used in the project, then there will definitely be benefits.