Boost logo

Boost :

From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2004-11-16 10:53:00


"David Abrahams" <dave_at_[hidden]> wrote in message
news:uk6smkkiq.fsf_at_boost-consulting.com...
> "Gennadiy Rozental" <gennadiy.rozental_at_[hidden]> writes:
>
> > An "active" solutions automatically place parameters in appropriate
slots by
> > single 'apply' call:
> >
> > class A {
> > public:
> > template<typename Params>
> > A( Params const& p ) { p.apply( *this ); }
> > };
> >
> > Even though "active" solutions in some cases provide an interface look
more
> > natural. I found that "passive" solution in most cases more flexible and
> > easier to implement. While in both cases one may employ runtime
> > polymorphism, with "passive interfaces it's more natural.

Just rereading this I realized that I actually meant it vicevisa. Active
solutions are more flexible and easier to impleemnt.

> > Note that
> > parameter may not necessary is just a simple value, it maybe some kind
of
> > optional feature and 'apply' method maybe not so trivial and even invoke
> > some functions. All in all both design seems to have heir advantages and
I
> > believe we need to provide support for both flavors.
>
> Hmm. AFAICT from your example an "active" solution requires a
> custom-built Params class that knows how to "apply" itself (in this
> case to class A). Because of that, I can't imagine what it could mean
> to "provide support" for an active approach. It doesn't seem like
> something a library can help with. Also, it seems as though the
> elements of the parameter infrastructure (e.g. a keyword class) will
> become special-purpose for the particular "apply" it needs to be able
> to perform, rather than reusable for several functions as in our
> approach. Am I missing something?

There is enough (like parameter combining anf interfaces and keywords) that
could be reused in a library.

> > II Interfaces
> >
> > a) Call interface and parameters combining
> >
> > IMO with some very rare exclusions (1/2 optional parameter) the named
> > parameter framework shouldn't require/expect multiple overloading of
target
> > function with different number of parameters. As well as any "impl"
> > functions. The only acceptable interface is the one with single Params
> > template parameters (in some cases one may provide positional interface
as
> > well, though it's rather exclusion case). This is applicable both to
active
> > and passive solutions:
> >
> > class A {
> > A() : ... {}
> >
> > template<typename Params>
> > A( Params const& p ) : m_name( p[name] ), m_gulp( p[gulp] ) {}
> > };
>
> Of course our library allows that usage. You can look on the
> "multiple overloading" case as though it was generated with varargs
> templates, which I hope we're getting in an upcoming version of C++.
> Hmm, we'd better make sure that feature can handle this case. ;-)
>
> > This immediately bring a need for automatic arguments combining.
> > There are several ways to do so, depending on requirements (BWT I
> > liked interface presented in some other post with using ',' as
> > combine operator).
>
> That's what our library does.

Hmm. Well, I did not find it nor in docs. Why IMO it's most important part
of functionality. I see it now in test. Why did you name function f_list?
Why not just f as rest of them?

> > b) Optional parameter support
> >
> > In case of active solutions there should be an interface to check
> > presence of specific argument. Submitted solution will cause compile
> > time error on access to non-supplied parameter. This may not be
> > always most convenient and may not be the case at all with different
> > implementation (runtime based)
>
> It's easy enough to check, actually.
>
> struct nil_t {} nil;
> template <class T> bool is_nil(T&) { return false; }
> bool is_nil(nil_t) { return true; }
>
> now
>
> is_nil(p[name | nil])
>
> will tell you if "name" was supplied. I guess we could build this
> into the library (with the corresponding compile-time check, of
> course).

It could be usefull.

> > c) Default value support
> >
> > I specifically dislike an interfaces provided to support default values.
> > They are unreasonably cryptic (who would remember difference between |
and
> > ||; and why | )
>
> That's pretty funny; it's meant to be memnonic.
>
> We use | because it means "or," as in
>
> either get the name OR if it's not supplied, use this value
>
> We use || to indicate lazy evaluation because in C++, the 2nd argument
> to || isn't evaluated unless the first one is supplied.
>
> either get the name OR if it's not supplied, evaluate this
> function and use the result.
>
> > but also misleading since default value is actually with
> > access brackets:
>
> I can't parse that. In what sense is the default value "with access
> brackets?" Do you mean it's "accessed with brackets?"

I meant "within brackets". My problem is that it's p[name | "abc"] while I
would prefer something like p[name] | "abc". Or even better something like a
nexplicit interface below.

> > There are several alternatives. My personal preference is :
> >
> > int name_ = p.is_present<name> ? p[name] : "abc"; // you will need some
MP
> > trick to make it compilable
> > or
> > int name_ = p.is_present( name ) ? p[value] : "abc"; // this assumes
> ^^^^^
> What's the significance of that?-------^^^^^

Could you rephrase the question? It's just an interface I would prefer.

> > runtime based implementation
> >
> > Active solutions doesn't have such issue. Whatever is there gets set
> > by apply call.
>
> Sure, but I don't see how a library can help you with it yet.

It could. I did that.

> > d) Type safety and restrictions
> >
> > I do not understand why wouldn't we keep data type somewhere around
> > keyword type and require one to supply specific type during
> > invocation.
>
> Because we looked at the use cases; the major example we could find
> was the Boost.Graph library, which is a library of function
> templates. We thought it would be bad if the library didn't work
> for function templates.

Sorry I am not familier with that example. Could you please give more
details on what exactly is wrong wit hstrict type checking?

> > This library instead invented special mechanism of imposing
> > restrictions.
>
> Not really; it used a de-facto standard approach for passing
> compile-time functions.

Yeah. But in C++ de-facto standard approach for enforcing parameters types
is to specify one.

> > e) Mix of named and positional parameters
> >
> > I don't believe it's actually a good idea to support such mix. IMO it
just
> > adding unnecessary confusion and possible source of users errors.. Let's
say
> > I expect 2 parameters: 1. string name 2. int value. call foo( value = 5,
> > "my_name" ) will fail, while foo( "my_name", value = 5 ) and foo( value
=
> > 5 ) won't. Too much chances to make mistake IMO.
>
> Python and I'm sure quite a few others do it that way; experience has
> shown that it causes no confusion.

I do not know about python, but in c++ I prefer named interface wouldn't
break by switching order of parameter specification.

> > III. Implementation
> >
> > IMO whatever design you prefer implementation shouldn't as complex and
> > cumbersome. Named parameters support is pretty simple task. This
submission
> > presents 1000 lines of tight MP code (and this is without numerous
> > includes). In majority of the cases much more simple and straightforward
> > solution is possible (with some acceptable IMO tradeoff). Following 80
lines
> > (I think it's possible to make it even smaller would I use mpl) should
> > basically present solution with similar tradeoff as submitted library
> > (without default value support, but IMO it would take another 40-60
lines,
> > just save it into keyword struct):
>
> and without the ability to control overload resolution,

What do you mean here? With an example.

> or to wrap function templates

Or this?

> and with the problem of keyword coupling (because of the integer indices).

What do you mean by coupling? That we need to supply unique integer id? I do
not see it as a major drawback. And it's definetly justified by the
simplicity of the solution.

> It's no fair claiming the solution should be
> simpler until you actually implement it. Toy examples don't count.

I did. And I do not believe it's toy example (at least no more that
submitted library). It does everything I need from named parameters, easy to
use and does not cost a lot.

> > Strict type checking on top of it.
>
> You say that like it's a _good_ thing.

Yes. I do believe strict type checking is good thing for both positional and
named function parameters.

> > This code works under gcc 3.4.2. Should work everywhere.
>
> Hah! I'll believe that when you've ported it ;-)

I did not use any advanced features (I don't think even PS). I did ported
similar solutions on numerous compilers.

> > As you may guess by now my vote is NO to accept this library. I
> > personally wouldn't be using it in current form and IMO as it stands
> > now it's just another collection of neat MP tricks.
>
> It's really _just_ another collection of neat MP tricks? You mean
> it's not even useful? Or what, exactly?

I wouldn't be using it. Why would I use canon to kill sparrow.

> --
> Dave Abrahams

Gennadiy


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