Recently I found Parameters library in the Boost. Honestly I didn't understand the reason why this is a part of Boost. When there is need to pass several parameters to the function you can make a structure from them, like:
struct Parameters
{
Parameters() : strParam("DEFAULT"), intParam(0) {}
string strParam;
int intParam;
};
void foo(const Parameters & params)
{
}
Parameters params;
params.intParam = 42;
foo(params);
This is very easy to write and understand. Now example with using Boost Parameters:
BOOST_PARAMETER_NAME(param1)
BOOST_PARAMETER_NAME(param2)
BOOST_PARAMETER_FUNCTION(
(void), // 1. parenthesized return type
someCompexFunction, // 2. name of the function template
tag, // 3. namespace of tag types
(optional // optional parameters, with defaults
(param1, *, 42)
(param2, *, std::string("default")) )
)
{
std::cout << param1 << param2;
}
someCompexFunction(param1_=42);
I think it's really complex, and the benefit is not that significant..
But now I see that some of the Boost libraries (Asio) use this technique. Is it considered a best practice to use this library to pass many arguments?
Or maybe there are real benefits of using this library that I don't see? Would you recommend using this library in the project?
Your technique requires creating a lot of temporaries (given enough parameters) and will be rather verbose in some cases. Something that is even more tricky is documentation. If you go down the route of configuration structs, you will have two places where you need to explain your parameters. Documenting Boost.Parameter functions is easy in comparison.
It also keeps the verbosity down and allows me to reuse arguments for whole families of functions instead of composing a new configuration carrier over and over again.
If you don't like the library, don't use it. It has several other drawbacks you haven't mentioned (heavy includes, high compile times).
Also, why not just provide the best of two worlds? One function using Boost.Parameters and another using configuration structs, where both dispatch on a common implementation. Manage headers correctly and the "don't pay for what you don't use" promise will be kept. The price is maintainability. But you can always deprecate one interface if your users don't like it.