Boost logo

Boost :

From: Hamish Mackenzie (boost_at_[hidden])
Date: 2002-02-06 23:41:45


On Thu, 2002-02-07 at 01:19, Howard Hinnant wrote:
> On Wednesday, February 6, 2002, at 07:37 PM, Hamish Mackenzie wrote:
>
> > So if move_traits is not specialized what should the default be?
> > * use copy construct/assign
> > * use swap
> > * no move allowed
> >
> > I am now leaning towards no move allowed (which I think was your
> > preference). Then specialize move_traits for existing classes that have
> > a good swap function.
>
> This is sounding like a promising compromise. In effect I believe this
> is telling class authors that you can implement move semantics in one of
> two ways:
>
> 1. Provide nothrow constructor and nothrow assignment taking a
> move_source.
> 2. Implement a nothrow default constructor and nothrow swap and
> register with move_traits.
>
> And if you do neither, code should be able to detect that you don't
> support move via move_traits (unless your class registers true with
> is_POD in which case you do support move with no effort required).

I will have a crack at this tomorrow.

> Aside: Be careful what std::containers you give move semantics to via
> choice 2. I know of implementations of std::containers that do not have
> a nothrow default constructor.

In these cases should we implement move (and not move_construct)?

We could have four seperate constant values in move_traits
 * has_move
 * has_move_nothrow
 * has_move_construct
 * has_move_construct_nothrow

> > I did try this hack
> >
> > template< typename T >
> > move_source< T > move_from_temporary( const T & source )
> > {
> > return move_source< T >( const_cast< T & >( source ) );
> > }
> >
> > And on the surface it seemed to work in gcc, but I didn't try it with
> > optomization on. It feels wrong to me perhaps someone with a copy of
> > the standard could clarify this.
>
> Not sure how this will be used. Will it mistakenly allow move from
> const?

It works like this

move_to( dest ) = move_from_temporary( f() );

But my guess is that the compiler may optomize the destruction of the
temporary and that our changing its members may cause errors. For
instance if it has stored the pointer to a buffer to free in a register,
we then switch the value in memory with the one in dest and it ends up
freeing the wrong buffer. At least with auto_ptr the compiler knows the
member data is mutable.

Another possiblity is

template< typename T >
inline void move_temporary( T & destination, T source )
{
  move( destination, source );
}

To allow

move_temporary( dest, f() );

How good are compilers at optomizing this? I seem to remember reading
about it in "Exceptional C++" but I can't find my copy right now.

> > I don't think we can do what auto_ptr does without changing the return
> > type of f(), which I don't think is a good idea.
>
> I agree that we can't change the return of f().
>
> > I still think a good compiler should be able to optomize out the copy
> > constructor from
> >
> > T temp( f() );
> > move_to( dest ) = move_from( temp );
>
> I think people will still complain. I don't believe they will want to
> do the extra typing to create a named temp.
>
> move_to(dest) = move_from(f());
>
> is so much easier.
>
> And I still like:
>
> dest = move(f());

The problem with this is that assignment must be a member of the class.
Would you settle for

T temp( f() );
dest << move( temp );

Where

template< typename T >
void operator <<( T & destination, move_source< T > source )
{
  move( destination, source );
}

> better. But I think this is mainly because I've yet to be convinced
> that we need the destruct-source (or relocation) versions of move. They
> don't help in the std::containers. I'm looking for the killer
> application where they can't be done without.

we could still loose the _from and use
 * move
 * move_destroy

Hamish Mackenzie


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