Blame tmp/source_release/adobe/move.hpp

Alec Leamas 5ed0b82
/*
Alec Leamas 5ed0b82
    Copyright 2005-2007 Adobe Systems Incorporated
Alec Leamas 5ed0b82
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
Alec Leamas 5ed0b82
    or a copy at http://stlab.adobe.com/licenses.html)
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#ifndef ADOBE_MOVE_HPP
Alec Leamas 5ed0b82
#define ADOBE_MOVE_HPP
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#include <cassert>
Alec Leamas 5ed0b82
#include <iterator>
Alec Leamas 5ed0b82
#include <memory>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#include <boost/iterator/iterator_adaptor.hpp>
Alec Leamas 5ed0b82
#include <boost/mpl/bool.hpp>
Alec Leamas 5ed0b82
#include <boost/mpl/and.hpp>
Alec Leamas 5ed0b82
#include <boost/mpl/or.hpp>
Alec Leamas 5ed0b82
#include <boost/mpl/not.hpp>
Alec Leamas 5ed0b82
#include <boost/mpl/assert.hpp>
Alec Leamas 5ed0b82
#include <boost/range/begin.hpp>
Alec Leamas 5ed0b82
#include <boost/range/end.hpp>
Alec Leamas 5ed0b82
#include <boost/type_traits/is_convertible.hpp>
Alec Leamas 5ed0b82
#include <boost/type_traits/is_same.hpp>
Alec Leamas 5ed0b82
#include <boost/type_traits/is_class.hpp>
Alec Leamas 5ed0b82
#include <boost/utility/enable_if.hpp>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\defgroup move_related Move Library
Alec Leamas 5ed0b82
\ingroup utility
Alec Leamas 5ed0b82
\brief
Alec Leamas 5ed0b82
The move library is a collection of utilities for creating and using types that leverage
Alec Leamas 5ed0b82
return value optimization (RVO) to avoid unnecessary copies.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\section move_tutorial Tutorial
Alec Leamas 5ed0b82
User defined types often have remote parts either because they are implemented using a
Alec Leamas 5ed0b82
pointer-to-implementation or are variable sized. Such objects can be expensive to copy
Alec Leamas 5ed0b82
and are often copied unnecessarily when they are returned from functions or stored in other
Alec Leamas 5ed0b82
objects or containers. The \ref move_related is a collection of utilities to implement types which
Alec Leamas 5ed0b82
can be moved to elide copying in such situations as well as utilities to assist in moving value.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Implementing a Movable Type
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
A movable type models \ref concept_movable. There are three components of a movable type:
Alec Leamas 5ed0b82
	- Satisfy the requirements of concept \ref concept_regular_type.
Alec Leamas 5ed0b82
	- Implement a move-ctor using move_from<>.
Alec Leamas 5ed0b82
	- Modify the assignment operator to take the operand by value and consume it.
Alec Leamas 5ed0b82
	
Alec Leamas 5ed0b82
A typical implementation of the move-ctor will simply extract the remote part, leaving the
Alec Leamas 5ed0b82
source in a destructible state.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
The assignment operator takes the operand parameter by value. Typically the simplest way
Alec Leamas 5ed0b82
to destory the local remote part and consume the remote part of the operand is to swap
Alec Leamas 5ed0b82
contents with the operand. This is similar to the copy-ctor and swap idiom for implementing
Alec Leamas 5ed0b82
assignment.
Alec Leamas 5ed0b82
	
Alec Leamas 5ed0b82
Listing 1 shows an example movable class that implements a typical pointer-to-implementation
Alec Leamas 5ed0b82
(PiPl) idiom and shows that it can be used as any regular type.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\code
Alec Leamas 5ed0b82
#include <iostream>
Alec Leamas 5ed0b82
#include <algorithm>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#include <boost/operators.hpp>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#include <adobe/move.hpp>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
using std::swap;
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
struct implementation : boost::equality_comparable<implementation>
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    explicit implementation(int x = 0) : member(x) { }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    implementation(const implementation& x) : member(x.member)
Alec Leamas 5ed0b82
    { std::cout << "copy remote part: " << member << std::endl; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    implementation& operator=(const implementation& x)
Alec Leamas 5ed0b82
    {
Alec Leamas 5ed0b82
        member = x.member;
Alec Leamas 5ed0b82
        std::cout << "assign remote part: " << member << std::endl;
Alec Leamas 5ed0b82
        return *this;
Alec Leamas 5ed0b82
    }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    friend bool operator==(const implementation& x, const implementation& y)
Alec Leamas 5ed0b82
    { return x.member == y.member; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    int member;
Alec Leamas 5ed0b82
};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
class movable : public boost::equality_comparable<movable>
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
 public:
Alec Leamas 5ed0b82
// model concept Regular
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
    explicit movable(int x = 0) : member(new implementation(x)) { }
Alec Leamas 5ed0b82
    ~movable() { delete member; }
Alec Leamas 5ed0b82
    movable(const movable& x) : member(new implementation(*x.member)) { }
Alec Leamas 5ed0b82
    // operator=() implemented below
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    friend bool operator==(const movable& x, const movable &y)
Alec Leamas 5ed0b82
    { return *x.member == *y.member; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    friend void swap(movable& x, movable& y)
Alec Leamas 5ed0b82
    { swap(x.member, y.member); }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
// model concept Movable
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    // move-ctor assumes ownership of remote part
Alec Leamas 5ed0b82
    movable(adobe::move_from<movable> x) : member(x.source.member)
Alec Leamas 5ed0b82
    { x.source.member = 0; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    // operator=() on a movable type takes parameter by value and consumes it
Alec Leamas 5ed0b82
    movable& operator=(movable x)
Alec Leamas 5ed0b82
    { swap(*this, x); return *this; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
 private:
Alec Leamas 5ed0b82
    implementation* member;
Alec Leamas 5ed0b82
};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
int main()
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    movable x(10);
Alec Leamas 5ed0b82
    movable y = x;
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
    return 0;
Alec Leamas 5ed0b82
}
Alec Leamas 5ed0b82
\endcode
Alec Leamas 5ed0b82
<center>Listing 1</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\verbatim
Alec Leamas 5ed0b82
copy remote part: 10
Alec Leamas 5ed0b82
\endverbatim
Alec Leamas 5ed0b82
<center>Output of Listing 1</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Returning a Movable Type
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
We can return a movable type from a function by value and unnessary copies will be avoided as
Alec Leamas 5ed0b82
Listing 2 illustrates:
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\code
Alec Leamas 5ed0b82
//...
Alec Leamas 5ed0b82
movable f(int x, int y)
Alec Leamas 5ed0b82
{ return movable(x * y); }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
int main()
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    movable x = f(10, 5);
Alec Leamas 5ed0b82
    movable y;
Alec Leamas 5ed0b82
    y = f(4, 3);
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
    return 0;
Alec Leamas 5ed0b82
}
Alec Leamas 5ed0b82
\endcode
Alec Leamas 5ed0b82
<center>Listing 2</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\verbatim
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\endverbatim
Alec Leamas 5ed0b82
<center>Ouput of Listing 2</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
In this example it is not necessary to make any copies. The result of f() is constructed directly
Alec Leamas 5ed0b82
in place for x through a compiler optimization known as return value optimization or RVO. In the
Alec Leamas 5ed0b82
case of assigning to y, the same optimization allows the compiler to construct the operand for
Alec Leamas 5ed0b82
assignment as the result of f() which is them moved into y.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Implementing a Sink Function
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
A sink is any function that copies it's argument, usually for the purpose of storing it.
Alec Leamas 5ed0b82
A sink is often a constructor or an insert function on a container. The \c operator=() on a movable
Alec Leamas 5ed0b82
type is a form of a sink function. To implement a sink function pass the argument by value and then
Alec Leamas 5ed0b82
use \c adobe::move() to move the argument into place. Note that this technique cannot be used to
Alec Leamas 5ed0b82
implement \c operator=() on because it relies on assignment. Listing 3 implements an example sink 
Alec Leamas 5ed0b82
function.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\code
Alec Leamas 5ed0b82
//...
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
struct sink
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
	explicit sink(movable x) : member(adobe::move(x)) { }
Alec Leamas 5ed0b82
	
Alec Leamas 5ed0b82
	movable member;
Alec Leamas 5ed0b82
};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
int main()
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    movable x = f(10, 5);
Alec Leamas 5ed0b82
    sink y(x);          // must copy.
Alec Leamas 5ed0b82
    sink z(f(20, 2));   // no copy.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
    return 0;
Alec Leamas 5ed0b82
}
Alec Leamas 5ed0b82
\endcode
Alec Leamas 5ed0b82
<center>Listing 3</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\verbatim
Alec Leamas 5ed0b82
copy remote part: 50
Alec Leamas 5ed0b82
\endverbatim
Alec Leamas 5ed0b82
<center>Output of Listing 3</center>
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
Here again unnessary copies are eliminated. Although adobe::move() can be used anytime to force the
Alec Leamas 5ed0b82
move of an object, it should only be used as part of an explicit sink function otherwise it hinders
Alec Leamas 5ed0b82
the understanding of code.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Utilities
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
There are many utilities as part of the move library which can be used to move elements instead of
Alec Leamas 5ed0b82
copying them. These are useful when building containers or dealing with sink operations which must
Alec Leamas 5ed0b82
manage a collection of movable objects. Generally these operations parallel the associated copying
Alec Leamas 5ed0b82
algorithms from STL. Examples:
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
MoveCopyComment
Alec Leamas 5ed0b82
adobe::move()std::copyNot to be confused with the single argument adobe::move()
Alec Leamas 5ed0b82
adobe::move_backward()std::copy_backward
Alec Leamas 5ed0b82
adobe::back_move_iterator()std::back_insert_iterator
Alec Leamas 5ed0b82
adobe::back_mover()std::back_inserter
Alec Leamas 5ed0b82
adobe::move_construct()std::construct
Alec Leamas 5ed0b82
adobe::uninitialized_move()std::uninitialized_copy
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Advanced Topics
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
The \c adobe::move() function is a NOP if the argument is not movable, however, when a non-movable
Alec Leamas 5ed0b82
item is passed to a sink this may still result in an unnecessary copy - one to the sink and one to
Alec Leamas 5ed0b82
copy the argument of the sink into place. To avoid the additional copy, two forms of a sink function
Alec Leamas 5ed0b82
can be provided, one for movable types and one for copyable types. The \c adobe::move_sink<> and
Alec Leamas 5ed0b82
\c adobe::copy_sink<> tags can be used to select between the two functions. See the
Alec Leamas 5ed0b82
implementation of \c adobe::move_construct() as an example.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
If a sink function is a member of a template class, the same issue with regard to unnecessary copies
Alec Leamas 5ed0b82
can occur. In this case, it is desirable to distinguish between the a copy and move sink as above
Alec Leamas 5ed0b82
but also to allow implicit conversions to the type stored in the container. To allow this use the
Alec Leamas 5ed0b82
two argument form of \c adobe::move_sink<> and \c adobe::copy_sink<>. See the implementation of
Alec Leamas 5ed0b82
\c adobe::vector::push_back() as an example.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Theory of Operation
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
to be written
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
\par Acknowledgments:
Alec Leamas 5ed0b82
The move library was inspired by the move library written by Dave Abrahams and the work on move
Alec Leamas 5ed0b82
done by Dave Abrahams and Howard Hinnant.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
namespace adobe {
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
namespace implementation {
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template <typename T>  
Alec Leamas 5ed0b82
struct class_has_move_assign {  
Alec Leamas 5ed0b82
    class type {
Alec Leamas 5ed0b82
        typedef T& (T::*E)(T t);  
Alec Leamas 5ed0b82
        typedef char (&no_type)[1];  
Alec Leamas 5ed0b82
        typedef char (&yes_type)[2];  
Alec Leamas 5ed0b82
        template <E e> struct sfinae { typedef yes_type type; };  
Alec Leamas 5ed0b82
        template <class U>  
Alec Leamas 5ed0b82
        static typename sfinae<&U::operator=>::type test(int);  
Alec Leamas 5ed0b82
        template <class U>  
Alec Leamas 5ed0b82
        static no_type test(...);  
Alec Leamas 5ed0b82
    public:  
Alec Leamas 5ed0b82
        enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};  
Alec Leamas 5ed0b82
    };
Alec Leamas 5ed0b82
 };  
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template<typename T>
Alec Leamas 5ed0b82
struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
class test_can_convert_anything { };
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
} //namespace implementation
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*
Alec Leamas 5ed0b82
	REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where
Alec Leamas 5ed0b82
	boost::is_convertible<T, T> fails to compile.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template <typename T, typename U>
Alec Leamas 5ed0b82
struct is_convertible : boost::mpl::or_<
Alec Leamas 5ed0b82
	boost::is_same<T, U>,
Alec Leamas 5ed0b82
	boost::is_convertible<T, U>
Alec Leamas 5ed0b82
> { };
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief move_from is used for move_ctors.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template <typename T>
Alec Leamas 5ed0b82
struct move_from
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    explicit move_from(T& x) : source(x) { }
Alec Leamas 5ed0b82
    T& source;
Alec Leamas 5ed0b82
};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief The is_movable trait can be used to identify movable types.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template <typename T>
Alec Leamas 5ed0b82
struct is_movable : boost::mpl::and_<
Alec Leamas 5ed0b82
                        boost::is_convertible<move_from<T>, T>,
Alec Leamas 5ed0b82
                        implementation::has_move_assign<T>,
Alec Leamas 5ed0b82
                        boost::mpl::not_<boost::is_convertible<implementation::test_can_convert_anything, T> >
Alec Leamas 5ed0b82
                    > { };
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief copy_sink and move_sink are used to select between overloaded operations according to
Alec Leamas 5ed0b82
 whether type T is movable and convertible to type U.
Alec Leamas 5ed0b82
\sa move
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename U = T,
Alec Leamas 5ed0b82
          typename R = void*>
Alec Leamas 5ed0b82
struct copy_sink : boost::enable_if<
Alec Leamas 5ed0b82
                        boost::mpl::and_<
Alec Leamas 5ed0b82
                            adobe::is_convertible<T, U>,                           
Alec Leamas 5ed0b82
                            boost::mpl::not_<is_movable<T> >
Alec Leamas 5ed0b82
                        >,
Alec Leamas 5ed0b82
                        R
Alec Leamas 5ed0b82
                    >
Alec Leamas 5ed0b82
{ };
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief move_sink and copy_sink are used to select between overloaded operations according to
Alec Leamas 5ed0b82
 whether type T is movable and convertible to type U.
Alec Leamas 5ed0b82
 \sa move
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename U = T,
Alec Leamas 5ed0b82
          typename R = void*>
Alec Leamas 5ed0b82
struct move_sink : boost::enable_if<
Alec Leamas 5ed0b82
                        boost::mpl::and_<
Alec Leamas 5ed0b82
                            adobe::is_convertible<T, U>,                            
Alec Leamas 5ed0b82
                            is_movable<T>
Alec Leamas 5ed0b82
                        >,
Alec Leamas 5ed0b82
                        R
Alec Leamas 5ed0b82
                    >
Alec Leamas 5ed0b82
{ };
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief This version of move is selected when T is_movable . It in turn calls the move
Alec Leamas 5ed0b82
constructor. This call, with the help of the return value optimization, will cause x to be moved
Alec Leamas 5ed0b82
instead of copied to its destination. See adobe/test/move/main.cpp for examples.
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template <typename T>
Alec Leamas 5ed0b82
T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief This version of move is selected when T is not movable . The net result will be that
Alec Leamas 5ed0b82
x gets copied.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template <typename T>
Alec Leamas 5ed0b82
T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief Iterator pair version of move. Similar to std::copy but with move semantics, 
Alec Leamas 5ed0b82
for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename O> // O models OutputIterator
Alec Leamas 5ed0b82
O move(I f, I l, O result)
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    while (f != l) {
Alec Leamas 5ed0b82
        *result = adobe::move(*f);
Alec Leamas 5ed0b82
        ++f; ++result;
Alec Leamas 5ed0b82
    }
Alec Leamas 5ed0b82
    return result;
Alec Leamas 5ed0b82
}
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief \ref concept_convertible_to_range version of move. Similar to copy but with move semantics, 
Alec Leamas 5ed0b82
for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename O> // O models OutputIterator
Alec Leamas 5ed0b82
inline O move(I& in, O out) { return adobe::move(boost::begin(in), boost::end(in), out); }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
 
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief Iterator pair version of move_backwards. Similar to std::copy_backwards but with move semantics, 
Alec Leamas 5ed0b82
for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename O> // O models BidirectionalIterator
Alec Leamas 5ed0b82
O move_backward(I f, I l, O result)
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    while (f != l) {
Alec Leamas 5ed0b82
        --l; --result;
Alec Leamas 5ed0b82
        *result = adobe::move(*l);
Alec Leamas 5ed0b82
    }
Alec Leamas 5ed0b82
    return result;
Alec Leamas 5ed0b82
}
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief \ref concept_convertible_to_range version of move_backwards. Similar to std::copy_backwards but 
Alec Leamas 5ed0b82
with move semantics, for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
template 
Alec Leamas 5ed0b82
          typename O> // O models BidirectionalIterator
Alec Leamas 5ed0b82
inline O move_backward(I& in, O out)
Alec Leamas 5ed0b82
{ return adobe::move_backward(boost::begin(in), boost::end(in), out); }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief Similar to std::back_insert_iterator but 
Alec Leamas 5ed0b82
with move semantics, for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template <typename C> // C models Container
Alec Leamas 5ed0b82
class back_move_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
Alec Leamas 5ed0b82
{
Alec Leamas 5ed0b82
    C* container_m;
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
 public:
Alec Leamas 5ed0b82
    typedef C container_type;
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    explicit back_move_iterator(C& x) : container_m(&x) { }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    back_move_iterator& operator=(typename C::value_type x)
Alec Leamas 5ed0b82
    { container_m->push_back(adobe::move(x)); return *this; }
Alec Leamas 5ed0b82
    
Alec Leamas 5ed0b82
    back_move_iterator& operator*() { return *this; }
Alec Leamas 5ed0b82
    back_move_iterator& operator++() { return *this; }
Alec Leamas 5ed0b82
    back_move_iterator& operator++(int) { return *this; }
Alec Leamas 5ed0b82
};
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*!
Alec Leamas 5ed0b82
\ingroup move_related
Alec Leamas 5ed0b82
\brief Similar to std::back_inserter but 
Alec Leamas 5ed0b82
with move semantics, for movable types, otherwise with copy semantics.
Alec Leamas 5ed0b82
*/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
template <typename C> // C models Container
Alec Leamas 5ed0b82
inline back_move_iterator<C> back_mover(C& x) { return back_move_iterator<C>(x); }
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
} // namespace adobe
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
#endif
Alec Leamas 5ed0b82
Alec Leamas 5ed0b82
/*************************************************************************************************/