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