Boost logo

Boost :

Subject: Re: [boost] Fwd: Re: [move] You can do it better: implementing push_back and handling implicit conversions
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2011-03-09 15:32:36


On 3/9/2011 11:58 AM, Ion Gaztañaga wrote:
> El 09/03/2011 2:25, Jeffrey Lee Hellrung, Jr. escribió:
>> Ion, I count 5 overloads of push_back in C++03 and 4 overloads in C++0x
>> for your solution. I believe one can get by with just 3 overloads in
>> C++03, and 1 in C++0x, but the path to "T construction" in my solution
>> is a little bit different than yours. I delay any T construction until
>> the placement new statement in priv_push_back. I don't know what your
>> requirements are in general, but for push_back, I think this should be
>> fine. The solution I sent you has maybe a slight disadvantage over
>> yours in that conversion errors would likely end up pointing to
>> priv_push_back, but if this is a concern, the template overloads of
>> push_back can be restricted (further) with enable_if (I think).
>
> I count 5 overloads for C++03 and 2 for C++0x (usual const T & and T&&).

Whoops! Yes, you're right.

> I don't know if emulation "placement construction" is right for
> convertible types, at least it should not occur in standard C++0x
> containers.

I *think* I know what you mean by this, but just to clarify: you believe
that push_back should behave as if it only accepted T const & and
T&&...? I.e., the placement new should only copy constructor or move
construct a T, not convert construct.

> std::list in C++0x can contain non-movable and non-copyable
> types, (some functions like resize(), require DefaultConstructible and
> emplace() requires EmplaceConstructible, but no MoveConstructible or
> CopyConstructible)

...sure...

> and in this case insert(position, value) should fail
> for convertible types.

By "should fail", you mean "should fail to compile, according to the
standard", and here "value" is not an object of the std::list
value_type, but some other type that's convertible to value_type,
correct? Again, just to clarify.

> I guess we should mimick that behaviour in C++03
> containers with emulated move semantics.

Well that seems to be up to the author of the container. If you're
looking to emulate the behavior of the std:: containers, including
restricting to the same set of valid expressions, then yes, I guess you
need to emulate push_back only receiving value_type const & and
value_type&& parameters. In this case, in this example, in C++03, one
can use 2 overloads of priv_push_back:

template< class U >
typename boost::enable_if<
     // strips const, &, and rv<> qualifiers
     is_same_sans_const_sans_reference<U,T>
>::type
priv_push_back(U& x)
{ new(&storage_) T(x); }

template< class U >
typename boost::disable_if<
     // strips const, &, and rv<> qualifiers
     is_same_sans_const_sans_reference<U,T>
>::type
priv_push_back(U& x)
// something to force the instantiation of a move/copy constructor
{ new(&storage_) T(T(x)); }

Alternatively, one could also put in some kind of static assertion in
the templated push_back overloads that enforces the existence of a
move/copy constructor whenever U isn't T (up to const and reference
qualifiers).

Yes, it's a bit more ugly, but if you were to document this as a general
technique or recommendation, I would ultimately let the container author
decide whether to allow "placement construction".

- Jeff


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