C++ "Named Parameter Idiom" VS. Boost::Parameter Library

C++ Named Parameter Idiom vs. Boost::Parameter library

Implementing the Named Parameter Idiom is really easy, almost about as easy as using Boost::Parameter, so it kind of boils down to one main point.

-Do you already have boost dependencies? If you don't, Boost::parameter isn't special enough to merit adding the dependency.

Personally I've never seen Boost::parameter in production code, 100% of the time its been a custom implementation of Named Parameters, but that's not necessarily a good thing.

Why are the arguments to BGL functions separated by dots, instead of commas?

The documentation explains what's going on:

Many of the Boost.Graph algorithms have a long list of parameters,
most of which have default values. This causes several problems.

[...]

A better solution is provided by bgl_named_params. This class allows
users to provide parameters is any order, and matches arguments to
parameters based on parameter names.

[...]

Each
of the arguments is passed to a function whose name indicates which
parameter the argument is for. Each of the named parameters is
separated by a period, not a comma
.

[...]

Typically the user never needs to deal with the bgl_named_params class
directly, since there are functions like boost::weight_map
that create
an instance of bgl_named_params.

See also What is the “Named Parameter Idiom”?.

Boost.Parameter: named template argument in combination with CRTP

A minimal example with no CRTP:

#include <boost/parameter.hpp>
#include <boost/static_assert.hpp>

BOOST_PARAMETER_TEMPLATE_KEYWORD(Policy1_is)
BOOST_PARAMETER_TEMPLATE_KEYWORD(Policy2_is)

typedef boost::parameter::parameters<
boost::parameter::optional<tag::Policy1_is>,
boost::parameter::optional<tag::Policy2_is>
> PolicySelector;

struct foo {};
struct bar {};
struct baz;
typedef typename PolicySelector::bind<foo, baz>::type Policies;
boost::parameter::value_type<Policies, tag::Policy1_is, bar>::type x; // <- !!!

So boost::parameter::value_type requires the policy selector to be based on complete types, which is not the case for your handwritten classes.

I'm not completely sure why a class would need itself as its own policy. If you need that, perhaps you could wrap an incomplete type in something complete:

struct CuriousBreadSlicer : BreadSlicer <
Policy1_is<CuriousBreadSlicer *> > // <- compiles

Or you could use your own wrap_incomplete_type<> template, for clarity.

When you use the policy, you can check if it's wrapped, and unwrap it.

Named? parameters in templates, functions

For functions you can use the Named Parameters Idiom (in both C++98 and C++0x).

See C++ FAQ item 10.20 What is the "Named Parameter Idiom"?.

For template arguments I think you can use the idea of wrapping, using "type carrier" types that by their type encode which template argument they are. It gets complex. You might check out the Boost Parameters library for ideas, but essentially, for template arguments I do not think it's worth spending time on (not to mention actually using) -- it's academic.

Cheers & hth.,

Questions about using a per-function-struct (parameter object) to emulate named arguments for options to function calls?

Can someone confirm it requires C++14 and not just C++11?

None of them. It requires C99/C11 designated initializers. Which are not part of any version of C++.

So what you're writing isn't standard C++ at all. It's based on compilers permitting C11 code in C++.

Do we expect a future C++1z or later to provide better approaches for named function parameters?

The closest you're likely to get in the forseeable future is for something like this paper (PDF) to get standardized in C++20. That provides C++ support for designated initializers, but even then, it won't be compatible with C99/11's designated initializers.

So if you continue with this hybrid C11/C++11 syntax, it may become illegal.

Why do Boost Parameter elected inheritance rather than composition?

EDIT: Ooopss! I posted the answer below because I misread your post. I thought you said the Boost library used composition over inheritance, not the other way around. Still, if its usefull for anyone... (See EDIT2 for what I think could be the answer for you question.)

I don't know the specific answer for the Boost Parameter Library. However, I can say that this is usually a better choice. The reason is because whenever you have the option to implement a relationship in more than one way, you should choose the weakest one (low coupling/high cohesion). Since inheritance is stronger than composition...

Notice that sometimes using private inhertiance can make it harder to implement exception-safe code too. Take operator==, for example. Using composition you can create a temporary and do the assignment with commit/rollback logic (assuming a correct construction of the object). But if you use inheritance, you'll probably do something like Base::operator==(obj) inside the operator== of the derived class. If that Base::operator==(obj) call throws, you risk your guarantees.

EDIT 2: Now, trying to answer what you really asked. This is what I could understand from the link you provided. Since I don't know all details of the library, please correct me if I'm wrong.

When you use composition for "implemented in terms of" you need one level of indirection for the delegation.


struct AImpl
{
//Dummy code, just for the example.
int get_int() const { return 10; }
};

struct A
{
AImpl * impl_;
int get_int() const { return impl->get_int(); }
/* ... */
};

In the case of the parameter-enabled constructor, you need to create an implementation class but you should still be able to use the "wrapper" class in a transparent way. This means that in the example from the link you mentioned, it's desired that you can manipulate myclass just like you would manipulate myclass_impl. This can only be done via inheritance. (Notice that in the example the inheritance is public, since it's the default for struct.)

I assume myclass_impl is supposed to be the "real" class, the one with the data, behavior, etc. Then, if you had a method like get_int() in it and if you didn't use inheritance you would be forced to write a get_int() wrapper in myclass just like I did above.



Related Topics



Leave a reply



Submit