|
Boost : |
From: Rene Rivera (grafik.list_at_[hidden])
Date: 2006-03-07 00:05:28
David Abrahams wrote:
> Rene Rivera <grafik.list_at_[hidden]> writes:
>
>> Daniel Wallin wrote:
>>> I don't think the rationale for this is completely expressed in the
>>> docs. The reason binding<> works like this is because of dangling
>>> references to defaults. Consider from your example above:
>>>
>>> something_t const & q = args[something | 0];
>>>
>>> When binding<> returns the default type here you will get a dangling
>>> reference here:
>>>
>>> int const& = args[something | 0]
>>>
>>> Our design handles this by letting binding<> return a reference type
>>> when an argument is bound to the keyword, and otherwise return the
>>> default type unchanged.
>> OK I understand what you are saying, but I don't see it :-) As far as I
>> understand from the docs the binding<>::type has nothing to do with the
>> default value as above as it happens before one gets to extracting the
>> value. I wasn't talking about changing the types that the operator[]
>> return.
>
> Consider the usage you're proposing when you /do/ want a reference to
> bind to the actual argument:
>
> typename binding<Args,tag::k,int>::type const& x = args[k | 0]
>
> If the "k" argument wasn't supplied, your int const& will be a
> dangling reference.
OK I see it now :-) But it still doesn't change my POV. Here's my
perspective with regards to the various use cases, when using defaults
since my initial examples did not use defaults:
1. Most of the time I want, and expect, copies. And many times this is
easy because on just writes out some preset type and assign:
int i = args[something | 1];
But that use case doesn't, to me, equate to the use case when it's not a
fixed type:
typedef remove_reference<remove_const<binding<...>::type>::type T;
T i = args[something | T(1)];
2. If I'm going to the trouble of getting the reference instead of the
value. I'm also going to go the extra effort to not get a dangling
reference as I would have even if I wasn't using boost::parameter:
int default_i = 0;
int const & i = args[something | default_i];
Which also doesn't equate to the case of a variable type:
typedef remove_reference<remove_const<binding<...>::type>::type T;
T detault_i(0);
T const & i = args[something | default_i];
3. I can see why having the binding type be a reference would signal
some forms of dangling refs:
typedef binding<...>::type T;
T i = args[something | T()]; // error
But that seems like a mistake one would make because one is expecting
the binding type to be the value_type.
4. And last, I can't remove_reference< remove_const<X> > on some types.
In particular last week I was trying to pass in a member function
pointer. Which the remove_* functions don't work on, or at least they
don't after boost::parameter adds the "const &". So I ended up having to
use a boost::function instead.
Basically it seems like I end up having to jump through hoops in many
use cases just to gain that compiler error on 1 use case and the default
value_type in 1 other use case. Maybe I'm just weird and I would see
things differently if I used things like the macros and forwarding
functions.
-- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk