📜 ⬆️ ⬇️

Named Boost Parameters

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.

  1. 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).
  2. 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.
  3. 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.

  1. Type of return value - necessarily in brackets
  2. Function name
  3. Namespace with parameters. BOOST_PARAMETER_NAME automatically puts ads in the tag
  4. 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 parameter

Those. 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

  1. Visibility - it is clear what we mean by numbers 1 and 111, the probability of getting confused / wrong is reduced
  2. 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.

Source: https://habr.com/ru/post/213015/


All Articles