
David Abrahams wrote:
Rene Rivera <grafik.list@redshift-software.com> 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