[parameter] Binding type.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[parameter] Binding type.

Rene Rivera
I've been Boost.Parameter a bit by now and I have some usability
feedback. There is one thing that currently bugs be a bit, the type
defined by parameter::binding. All my uses so far have been of the form:

typedef typename
   boost::remove_reference<
     boost::remove_const<
       boost::parameter::binding<ArgPack,tag::something>::type
       >::type
     >::type
   something_t;

something_t s = args[something];

Or equivalent thereof. So every use I have I end up removing the ref and
const because I'm really interested in the original type, and hence want
to make a copy. Now I understand the rational outlined in "Eliminating
Copies"
<http://www.boost.org/libs/parameter/doc/html/index.html#eliminating-copies>.
But I think that isn't enough of a justification for dirtying up the
user interface, as above. I'd rather that the binding type where the
value type so that one would have:

typedef typename
   boost::parameter::binding<ArgPack,tag::something>::type
   something_t;

something_t s = args[something];

Having it that way one still has the option of more naturally using the
reference type as;

something_t const & q = args[something];

And possibly also providing the container standard binding::value_type,
and binding::const_reference.



--
-- 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [parameter] Binding type.

Daniel Wallin
Rene Rivera wrote:

> I've been Boost.Parameter a bit by now and I have some usability
> feedback. There is one thing that currently bugs be a bit, the type
> defined by parameter::binding. All my uses so far have been of the form:
>
> typedef typename
>    boost::remove_reference<
>      boost::remove_const<
>        boost::parameter::binding<ArgPack,tag::something>::type
>        >::type
>      >::type
>    something_t;
>
> something_t s = args[something];
>
> Or equivalent thereof. So every use I have I end up removing the ref and
> const because I'm really interested in the original type, and hence want
> to make a copy. Now I understand the rational outlined in "Eliminating
> Copies"
> <http://www.boost.org/libs/parameter/doc/html/index.html#eliminating-copies>.
> But I think that isn't enough of a justification for dirtying up the
> user interface, as above. I'd rather that the binding type where the
> value type so that one would have:
>
> typedef typename
>    boost::parameter::binding<ArgPack,tag::something>::type
>    something_t;
>
> something_t s = args[something];
>
> Having it that way one still has the option of more naturally using the
> reference type as;
>
> something_t const & q = args[something];

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.

I would consider adding a binding_value<> metafunction though.

--
Daniel Wallin

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [parameter] Binding type.

Rene Rivera
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. And also from the docs, the binding<> function has it's own way
of declaring what the default type should be, which could be different
than the default value AFAICT.

Are you saying that operator[] uses the binding<>::type, instead of
using the internal "reference" type. Looking at code again... Ah yes it
does, but not for all compilers, in some it returns the reference type.
I think I would consider that a bug ;-)

But given that, would not what I suggested of having
binding<>::value_type, binding<>::const_reference, binding<>::reference,
etc. And then either having the operator[] use the binding<>::reference.
  Or another less incompatible change would be to just make those extra
binding types available. And the users could use the value_type in most
cases.

> I would consider adding a binding_value<> metafunction though.

Adding types to the binding<> function seems easier to me. But then I
didn't write the code :-)


--
-- 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [parameter] Binding type.

David Abrahams
Rene Rivera <[hidden email]> 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.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [parameter] Binding type.

Rene Rivera
David Abrahams wrote:

> Rene Rivera <[hidden email]> 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
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [parameter] Binding type.

David Abrahams
Rene Rivera <[hidden email]> writes:

> David Abrahams wrote:
>> Rene Rivera <[hidden email]> writes:
>>
>> 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.

Okay.  I'm not sure why, but that may not matter.  What matters is
that it's _your_ desire and expectation.  Do we have any reason to
think others will feel the same way?

I have no problem with adding a value_binding<> template that does
what you want, but so far I don't see why we should change binding<>
itself.

> 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)];

What do you mean by "equate?"  Are you just saying, "it isn't so easy
in that case?"

You know, you can always write this once:

    template <class A, class K, class D = void>
    struct my_binding
      : remove_const<
           typename remove_reference<
               typename binding<A,K,D>::type
           >::type
        >
    {};

> 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];

That doesn't seem like a good enough reason to make binding<> that
much more unsafe.

> 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

Huh?  What error?  And what is signalled?

> But that seems like a mistake one would make because one is expecting
> the binding type to be the value_type.

I'm lost

> 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 &".

That should be fixed, then!  But are you sure your problem isn't that
you have the remove_ functions inside-out?

   remove_reference<remove_const<binding<...>::type>::type

That will only remove reference-ness, but not constness, from a
reference-to-const.  The following compiles just fine for me, FWIW
(g++-3.4.4):

  #include <boost/mpl/assert.hpp>
  #include <boost/type_traits/is_same.hpp>
  #include <boost/type_traits/remove_const.hpp>
  #include <boost/type_traits/remove_reference.hpp>

  struct X { int g(); };

  template <class T> int f(T const& x)
  {
      using namespace boost;
      typedef T const& tcr;

      BOOST_MPL_ASSERT((
          is_same<
              typename remove_const<
                  typename remove_reference< tcr >::type
              >::type
          , T>));

      return 0;
  }

  int x = f(&X::g);

But if I invert the const and reference, of course it fails.

> 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.

Sorry, I'm totally lost.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost