Boost logo

Boost :

From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2004-11-23 09:37:05


"Doug Gregor" <dgregor_at_[hidden]> wrote in message
news:E3214120-3D4F-11D9-836D-000D932B7224_at_cs.indiana.edu...
> On Nov 23, 2004, at 1:10 AM, Gennadiy Rozental wrote:
> > Problem implement function with 2 named parameter interface where
> > parameter
> > 'value' is not fixed type but should comply to compile time predicate
> > is_movable and parameter name is string:
> >
> > Submitted library solution:
> > ------------------------------
> >
> > keyword<struct name_t> name;
> > keyword<struct value_t> value;
> >
> > struct f_keywords : keywords<
> > named_param<
> > name_t
> > , boost::mpl::false_
> > , boost::is_convertible<boost::mpl::_, std::string>
> >>
> > , named_param<
> > value_t
> > , boost::mpl::false_
> > , is_movable<boost::mpl::_>
> >>
> >>
> > {};
> >
> > template<typename MovableType>
> > void f_impl(std::string name, MovableType v )
> > {
> > ...
> > }
> >
> > template<class Params>
> > void f(Params const& p, typename f_keywords::restrict<Params>::type =
> > f_keywords())
> > // I am not actually quite sure whether above is a proper way to
> > enforce a
> > restriction
> > {
> > f_impl( p[name], p[value]);
> > }
>
> As I understand the library, the code you have written in correct.
>
> > My suggested solution
> > ------------------------------------
> >
> > typed_keyword<std::string,struct name_t> name;
> > keyword<struct name_t> value;
> >
> > template<typename MovableType>
> > typename boost::enable_if<is_movable<MovableType>, void>::type
> > f_impl(std::string name, MovableType v )
> > {
> > ...
> > }
> >
> > template<class Params>
> > void f(Params const& p)
> > {
> > f_impl( p[name], p[value]);
> > }
> >
> > ------------------------------------
> >
> > Now let's hear peoples subjective opinions on above choice. My
> > position that
> > library should only provide support for strict type checking. Any other
> > "more flexible" restrictions are user responsibility (if necessary).
>
> There is one subtle (but important) objective difference between the
> two: with the code for the library up for review, the restrictions
> happen for the call to "f", so if one tries to pass a non-movable type
> for the value, the end result will be that "f' is removed from the
> overload set and the compiler will emit an error stating that no call
> to "f" satisfies the argument list (or another "f" will be chosen).
> With your library, the restriction occurs at the level of "f_impl", so
> passing a non-movable value to "f" will actually call that "f", but the
> instantiation will fail within "f_impl". In essence, the library under
> review provides earlier checking of the arguments than your solution,
> so that functions that may support named parameters can be eliminated
> from the overload set if they don't meet the requirements.

1. It really trivial to implement the restriction on public level:

template<class Params>
typename boost::enable_if<is_movable<typename type_of<name,Params> >,
void>::type
f(Params const& p)
{
    f_impl( p[name], p[value]);
}

where type_of is very simple metafunction the deduce parameter value type
given parameter list and keyword.

2. I yet to see the reason why would anyone would prefer several overloads
of top level interface. See below for more on this

> Granted, your typed_keyword permits earlier detection of certain typing
> errors. For instance, if I try to write "name = 5", your library will
> abort the compilation at that expression but the library under review
> will instead remove "f" from the overload set if it is called. However,
> there is a potential price to be paid for this earlier checking: the
> name "name" has now been reserved for string parameters and cannot be
> reused without introducing a new "name" keyword in some other scope
> with a different type.

1. That is not true. Nothing prevent me from introduction of keyword name in
different namespace/compilation unit. Actually in most cases I use keywords
with namespace qualifiers: sock::name, cla::name, factory::name e.t.c.

2. If you implement several related function you may reuse the same typed
keyword in most cases it wouldn't be an issue since all functions expect the
same value type.

3. IMO It's bad idea to introduce global keywords used by various
independent functions for different purposes and different data types. For
example:

new window( size = make_pair(10,20) );
new listbox( size = 10 );
new Jeans( size = "36x30" );
new Bowl( size = 5.675 );

I don't see above as a good practice and library shouldn't encourage it.
Instead one should either use difference namespaces (see 1) or different
keywords: dimensions, size, cloth_size, volume.

> My (subjective) expectation is that a library
> may start by using typed keywords, but as the library evolves and more
> functions gain named parameters I'd expected those typed keywords to
> become non-typed keywords. There is no place in the BGL, for instance,
> where I would consider using a typed keyword.

That Ok. Unfortunately I am not that familiar with library but I do not
believe BGL is the best example. BGL is template based library solution. In
an end user's code my expectation is that in most cases one would use typed
keywords.

> Another subjective difference between the two is in the call to "f".
> The library under review supports the syntax:
>
> f(name = "wibble", value = int);
>
> whereas, as I understand it, your library supports the syntax:
>
> f((name = "wibble", value = int));
>
> I'm not going to weigh in on this issue.

Submitted library allow both syntaxes. I would never use first though. In my
experience named parameters interface is most valuable facing numerous
optional function arguments. Why would I want to provide 10 overloads for
the same functions with different number of arguments, where 1 suffices?

> Doug

Gennadiy


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk