Boost logo

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

-- Grafik - Don't Assume Anything
-- Redshift Software, Inc. -
-- rrivera/ - grafik/
-- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

Boost list run by bdawes at, gregod at, cpdaniel at, john at