Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-09-27 07:22:51

On Sep 27, 2004, at 2:46 AM, Thorsten Ottosen wrote:

> "Howard Hinnant" <hinnant_at_[hidden]> wrote in message
> | container<sole_ptr<T>> will have the same overhead as that
> demonstrated
> | in the Smart Container library. A big difference will be that
> | iterators into the container will dereference smart pointers, and not
> | the pointed-to elements. I also anticipate C++0X will contain some
> | really slick indirect_iterator types that will transform
> | container<sole_ptr<T>>::iterator appropriately. These will likely be
> | heavily influenced by (if not based on) the Boost.Iterator Library.
> I assume that there will still be some differences:
> 1. a large part of the in this library is indirected, eg. front() in
> container<sole_ptr<T>> would return
> sole_ptr<T>


> 2. release() and clone() can be made faster by moving instead of using
> an
> std::auto_ptr<> as today


> 3. your map iterators would be different

Right, just smart pointers to pair<const sole_ptr<T>, U>.

> 4. If you do intend that the interface of container<sole_ptr<T>> has
> the same
> interface as container<T>,
> then you loose the domain specific interface and the Clonable
> metaphor

Right again.

> | Assuming things go just peachy, all std::containers will be
> move-aware
> | and thus able to contain move-only types like sole_ptr<T>. Also I
> | would like to see all in-place-mutating std:: sequence algorithms
> | (remove_if, unique, etc.) rewritten to deal with ranges of move-only
> | types as well. Such algorithms, if not rewritten for move-only types
> | will fail at compile time (as opposed to run time) for move-only
> types.
> That would be nice. If all mutating algorithms would be guaranteed to
> call
> a swap and never use a copy-constructor, I think we could make an
> iterator
> for the smart containers that was indirected *and* did "the right
> thing" in
> those algorithms.

Agreed, sort of. We don't want to mandate that all algorithms call
swap. That would be too expensive for some algorithms (like remove)
when operating on sequences of some types (like int or complex<T>).
Rather I would like to mandate that algorithms such as remove work for
movable but non-copyable types. I.e. internally where remove today
might say:

*j = *i;

it would instead have to code:

*j = move(*i);

This might end up calling swap for some types, if the author of that
type has implemented move assignment with swap. For other types (like
int, or complex<T>), there will be no move assignment, and the above
change will make absolutely no difference in behavior or efficiency
(right down to the assembly that is generated).

All move(*i) does is tell the compiler to treat *i as an rvalue instead
of an lvalue. Then it is up to the author of *i to overload assignment
on rvalues (or not).

> | container<sole_ptr<T>> is not copyable nor copy-assignable.
> | container<sole_ptr<T>> is movable. Thus sequences of
> | container<sole_ptr<T>> (container<container<sole_ptr<T>>>) can also
> be
> | operated on by move-aware in-place-mutating sequence algorithms.
> |
> | Elements of container<sole_ptr<T>> can't be copied into or out of the
> | container with copy syntax:
> |
> | sole_ptr<T> t = v[i]; // compile time error
> |
> | But elements can be moved into or out of the container:
> |
> | sole_ptr<T> t = move(v[i]);
> | v.push_back(move(t));
> so move(v[i]) must also erase the element and then move
> the rest of the vector one place back?

Nope. move(v[i]) would move from the sole_ptr<T> at i, but not erase
it. v[i] would now own nothing. This is another difference between
this future language I'm describing, and the Smart Container Library.
The former allows null pointers where the latter doesn't.

> | This future move-aware
> | container<clone_ptr<T>> would not clone objects as it moved them
> around
> | internally, but would clone objects for the purpose of copying them
> | into or out of the container,
> sounds expensive to me.

<nod> If clients wanted to, they could move clone_ptr<T> into and out
of the container instead of copy it in and out. For rvalue
clone_ptr<T>'s, this would happen automatically, but for lvalue
clone_ptr<T> the client would have to explicitly request the move.


v.push_back(clone_ptr<base>(new derived)); // rvalue clone_ptr moved
into v
clone_ptr<base> p(new derived);
v.push_back(p); // p copied/cloned into v
v.push_back(move(p)); // p moved into v, p now null


Boost list run by bdawes at, gregod at, cpdaniel at, john at