|
Boost : |
From: Doug Gregor (dgregor_at_[hidden])
Date: 2004-11-23 08:02:10
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.
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. 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.
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.
Doug
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk