|
Boost : |
From: Sean Parent (sparent_at_[hidden])
Date: 2002-02-06 15:56:59
on 2/5/02 4:40 PM, Howard Hinnant at hinnant_at_[hidden] wrote:
> I think I misstated my goal. I'm hoping that containers will be able to
> detect and use move semantics as an internal optimization, not effecting
> the container's interface.
Sorry - I had viewed this as a splinter to the thread on doing an
auto_ptr_vector, which I had suggested become generalized to support any
object that doesn't support copy semantics but does support some combination
of move / swap.
It was correctly pointed out, that swap can be implemented using
constructing moves (in the same way it is done with copying, through a
temp). But in the case of a non-POD class, I don't think this is a win
unless you define the source from the move to have been destructed as a
result of the move (call this relocate).
The move vs. relocate semantics would be:
move - moving a source A into uninitialized memory B. The result leaves A in
an indeterminate but destructible state. "Copy" construction of an auto_ptr
is an example.
relocate - moving a source A into uninitialized memory B. The result leaves
A in a destructed state. Requires the source A is also managed with
placement new and delete.
The relocate construct would be useful for container optimization - but I
think the complexities of implementing it for anything that can't be treated
as a POD (just do a memcopy for the relocate) is difficult. It may be worth
having a trait though for objects that can use memcopy to relocate.
The first item, I think is simplest to implement using a non-throwing
constructor (one that constructs an object upon which the only valid
operation is destruction) and a swap. That's not to say that this is how you
would have to implement it- however there are many existing classes that
would meet these requirements. So let's define move as:
template <class T>
T* safe_construct(void* placement) throw()
{
return new(placement)T(std::nothrow);
}
template <class T>
T* move(void* placement, T& x) throw()
{
T* result (safe_construct<T>(placement));
std::swap(*result, x);
return result;
}
Specializations can be provided for either safe construction and/or move and
an is_movable trait can be added to the trait library. For items that are
movable, I think you can change the exception guarantee from basic to
transactional without a performance penalty in the non-exception case in the
std containers (assuming they are re-implemented of course). You can also
build containers (or provide an extended interface to the existing
containers) for types that only support move and not copy operations (like
auto_ptr).
Sean
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk