move.qbk 37.3 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
[/
 / Copyright (c) 2008-2010 Ion Gaztanaga
 /
 / Distributed under the Boost Software License, Version 1.0. (See accompanying
 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 /]
[library Boost.Move
    [quickbook 1.5]
    [authors [Gaztanaga, Ion]]
    [copyright 2008-2014 Ion Gaztanaga]
    [id move]
    [dirname move]
    [purpose Move semantics]
    [license
        Distributed under the Boost Software License, Version 1.0.
        (See accompanying file LICENSE_1_0.txt or copy at
        [@http://www.boost.org/LICENSE_1_0.txt])
    ]
]

[important To be able to use containers of movable-only values in C++03 mode you will need to use containers
supporting move semantics, like [*Boost.Container] containers]

[section:tested_compilers Tested compilers]

[*Boost.Move] has been tested in the following compilers/platforms:

*  Visual C++ >= 7.1.
*  GCC >= 4.1.

[warning GCC < 4.3 and MSVC < 9.0 are deprecated and will be removed in the next version.]

[endsect]

[section:what_is_boost_move What is Boost.Move?]

Rvalue references are a major C++0x feature, enabling move semantics for C++ values. However, we
don't need C++0x compilers to take advantage of move semanatics. [*Boost.Move] emulates C++0x
move semantics in C++03 compilers and allows writing portable code that works optimally in C++03 
and C++0x compilers.

[endsect]

[section:introduction Introduction]

[note

  The first 3 chapters are the adapted from the article
 [@http://www.artima.com/cppsource/rvalue.html ['A Brief Introduction to Rvalue References]]
 by Howard E. Hinnant, Bjarne Stroustrup, and Bronek Kozicki

]

Copying can be expensive. For example, for vectors `v2=v1` typically involves a function call,
a memory allocation, and a loop. This is of course acceptable where we actually need two copies of
a vector, but in many cases, we don't: We often copy a `vector` from one place to another, just to
proceed to overwrite the old copy. Consider: 

[c++]

   template <class T> void swap(T& a, T& b)
   {
      T tmp(a);   // now we have two copies of a
      a = b;      // now we have two copies of b
      b = tmp;    // now we have two copies of tmp (aka a)
   }

But, we didn't want to have any copies of a or b, we just wanted to swap them. Let's try again: 

[c++]

   template <class T> void swap(T& a, T& b)
   {
      T tmp(::boost::move(a));
      a = ::boost::move(b);   
      b = ::boost::move(tmp);
   }

This `move()` gives its target the value of its argument, but is not obliged to preserve the value
of its source. So, for a `vector`, `move()` could reasonably be expected to leave its argument as
a zero-capacity vector to avoid having to copy all the elements. In other words, [*move is a potentially
destructive copy].

In this particular case, we could have optimized swap by a specialization. However, we can't
specialize every function that copies a large object just before it deletes or overwrites it. That
would be unmanageable. 

In C++0x, move semantics are implemented with the introduction of rvalue references. They allow us to
implement `move()` without verbosity or runtime overhead. [*Boost.Move] is a library that offers tools
to implement those move semantics not only in compilers with `rvalue references` but also in compilers
conforming to C++03.

[endsect]

[section:implementing_movable_classes Implementing copyable and movable classes]

[import ../example/doc_clone_ptr.cpp]

[section:copyable_and_movable_cpp0x Copyable and movable classes in C++0x]

Consider a simple handle class that owns a resource and also provides copy semantics
(copy constructor and assignment). For example a `clone_ptr` might own a pointer, and call
`clone()` on it for copying purposes: 

[c++]

   template <class T>
   class clone_ptr
   {
      private:
      T* ptr;

      public:
      // construction
      explicit clone_ptr(T* p = 0) : ptr(p) {}

      // destruction
      ~clone_ptr() { delete ptr; }

      // copy semantics
      clone_ptr(const clone_ptr& p)
         : ptr(p.ptr ? p.ptr->clone() : 0) {}

      clone_ptr& operator=(const clone_ptr& p)
      {
         if (this != &p)
         {
            T *p = p.ptr ? p.ptr->clone() : 0;
            delete ptr;
            ptr = p;
         }
         return *this;
      }

      // move semantics
      clone_ptr(clone_ptr&& p)
         : ptr(p.ptr) { p.ptr = 0; }

      clone_ptr& operator=(clone_ptr&& p)
      {
         if(this != &p)
         {
            std::swap(ptr, p.ptr);
            delete p.ptr;
            p.ptr = 0;
         }
         return *this;
      }

      // Other operations...
   };

`clone_ptr` has expected copy constructor and assignment semantics, duplicating resources when copying.
Note that copy constructing or assigning a `clone_ptr` is a relatively expensive operation: 

[copy_clone_ptr]

`clone_ptr` is code that you might find in today's books on C++, except for the part marked as
`move semantics`. That part is implemented in terms of C++0x `rvalue references`. You can find
some good introduction and tutorials on rvalue references in these papers:

*  [@http://www.artima.com/cppsource/rvalue.html ['A Brief Introduction to Rvalue References]]
*  [@http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx ['Rvalue References: C++0x Features in VC10, Part 2]]

When the source of the copy is known to be a `rvalue` (e.g.: a temporary object), one can avoid the
potentially expensive `clone()` operation by pilfering source's pointer (no one will notice!). The move
constructor above does exactly that, leaving the rvalue in a default constructed state. The move assignment
operator simply does the same freeing old resources.

Now when code tries to copy a rvalue `clone_ptr`, or if that code explicitly gives permission to
consider the source of the copy a rvalue (using `boost::move`), the operation will execute much faster. 

[move_clone_ptr]

[endsect]

[section:copyable_and_movable_cpp03 Copyable and movable classes in portable syntax for both C++03 and C++0x compilers]

Many aspects of move semantics can be emulated for compilers not supporting `rvalue references`
and [*Boost.Move] offers tools for that purpose. With [*Boost.Move] we can write `clone_ptr`
so that it will work both in compilers with rvalue references and those who conform to C++03.
You just need to follow these simple steps:

* Put the following macro in the [*private] section:
  [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE(classname)]
* Leave copy constructor as is.
* Write a copy assignment taking the parameter as
  [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF(classname)]
* Write a move constructor and a move assignment taking the parameter as
  [macroref BOOST_RV_REF BOOST_RV_REF(classname)]

Let's see how are applied to `clone_ptr`:

[clone_ptr_def]

[endsect]

[*Question]: What about types that don't own resources? (E.g. `std::complex`?) 

No work needs to be done in that case. The copy constructor is already optimal.

[endsect]

[section:composition_inheritance Composition or inheritance]

For classes made up of other classes (via either composition or inheritance), the move constructor
and move assignment can be easily coded using the `boost::move` function:

[clone_ptr_base_derived]

[important Due to limitations in the emulation code, a cast to `Base &` is needed before moving the base part in the move
constructor and call Base's move constructor instead of the copy constructor.]

Each subobject will now be treated individually, calling move to bind to the subobject's move
constructors and move assignment operators. `Member` has move operations coded (just like
our earlier `clone_ptr` example) which will completely avoid the tremendously more expensive
copy operations:

[clone_ptr_move_derived]

Note above that the argument x is treated as a lvalue reference. That's why it is necessary to
say `move(x)` instead of just x when passing down to the base class. This is a key safety feature of move
semantics designed to prevent accidently moving twice from some named variable. All moves from 
lvalues occur explicitly.

[endsect]

[section:movable_only_classes Movable but Non-Copyable Types]

Some types are not amenable to copy semantics but can still be made movable. For example: 

*  `unique_ptr` (non-shared, non-copyable ownership) 
*  A type representing a thread of execution
*  A type representing a file descriptor

By making such types movable (though still non-copyable) their utility is tremendously
increased. Movable but non-copyable types can be returned by value from factory functions:

[c++]

   file_descriptor create_file(/* ... */);
   //...
   file_descriptor data_file;
   //...
   data_file = create_file(/* ... */);  // No copies!

In the above example, the underlying file handle is passed from object to object, as long
as the source `file_descriptor` is a rvalue. At all times, there is still only one underlying file
handle, and only one `file_descriptor` owns it at a time.

To write a movable but not copyable type in portable syntax, you need to follow these simple steps:

* Put the following macro in the [*private] section:
  [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE(classname)]
* Write a move constructor and a move assignment taking the parameter as
  [macroref BOOST_RV_REF BOOST_RV_REF(classname)]

Here's the definition of `file descriptor` using portable syntax:

[import ../example/doc_file_descriptor.cpp]
[file_descriptor_def]

[/
 /Many standard algorithms benefit from moving elements of the sequence as opposed to
 /copying them. This not only provides better performance (like the improved `swap`
 /implementation described above), but also allows these algorithms to operate on movable
 /but non-copyable types. For example the following code sorts a `vector<unique_ptr<T>>`
 /based on comparing the pointed-to types: 
 /
 /[c++]
 /
 /   struct indirect_less
 /   {
 /      template <class T>
 /      bool operator()(const T& x, const T& y)
 /         {return *x < *y;}
 /   };
 /   ...
 /   std::vector<std::unique_ptr<A>> v;
 /   ...
 /   std::sort(v.begin(), v.end(), indirect_less());
 /
 /
 /As sort moves the unique_ptr's around, it will use swap (which no longer requires Copyability)
 /or move construction / move assignment. Thus during the entire algorithm, the invariant that
 /each item is owned and referenced by one and only one smart pointer is maintained. If the
 /algorithm were to attempt a copy (say by programming mistake) a compile time error would result. 
 /]

[endsect]

[section:move_and_containers Containers and move semantics]

Movable but non-copyable types can be safely inserted into containers and
movable and copyable types are more efficiently handled if those containers
internally use move semantics instead of copy semantics.
If the container needs to "change the location" of an element
internally (e.g. vector reallocation) it will move the element instead of copying it.
[*Boost.Container] containers are move-aware so you can write the following:

[file_descriptor_example]

[endsect]

[section:construct_forwarding Constructor Forwarding]

Consider writing a generic factory function that returns an object for a newly
constructed generic type. Factory functions such as this are valuable for encapsulating
and localizing the allocation of resources. Obviously, the factory function must accept
exactly the same sets of arguments as the constructors of the type of objects constructed:

[c++]

   template<class T> T* factory_new()
   {  return new T();  }

   template<class T> T* factory_new(a1)
   {  return new T(a1);  }

   template<class T> T* factory_new(a1, a2)
   {  return new T(a1, a2);  }

Unfortunately, in C++03 the much bigger issue with this approach is that the N-argument case
would require 2^N overloads, immediately discounting this as a general solution. Fortunately,
most constructors take arguments by value, by const-reference or by rvalue reference. If these
limitations are accepted, the forwarding emulation of a N-argument case requires just N overloads.
This library makes this emulation easy with the help of `BOOST_FWD_REF` and
`boost::forward`:

[import ../example/doc_construct_forward.cpp]
[construct_forward_example]

Constructor forwarding comes in handy to implement placement insertion in containers with
just N overloads if the implementor accepts the limitations of this type of forwarding for
C++03 compilers. In compilers with rvalue references perfect forwarding is achieved.

[endsect]

[section:move_return Implicit Move when returning a local object]

The C++ standard specifies situations where an implicit move operation is safe and the
compiler can use it in cases were the (Named) Return Value Optimization) can't be used.
The typical use case is when a function returns a named (non-temporary) object by value
and the following code will perfectly compile in C++11:

[c++]

   //Even if movable can't be copied
   //the compiler will call the move-constructor
   //to generate the return value
   //
   //The compiler can also optimize out the move
   //and directly construct the object 'm'
   movable factory()
   {
      movable tmp;
      m = ...
      //(1) moved instead of copied
      return tmp;
   };

   //Initialize object
   movable m(factory());


In compilers without rvalue references and some non-conforming compilers (such as Visual C++ 2010/2012)
the line marked with `(1)` would trigger a compilation error because `movable` can't be copied. Using a explicit
`::boost::move(tmp)` would workaround this limitation but it would code suboptimal in C++11 compilers
(as the compile could not use (N)RVO to optimize-away the copy/move).

[*Boost.Move] offers an additional macro called [macroref BOOST_MOVE_RET BOOST_MOVE_RET] that can be used to
alleviate this problem obtaining portable move-on-return semantics. Let's use the previously presented
movable-only `movable` class with classes `copyable` (copy-only type), `copy_movable` (can be copied and moved) and
`non_copy_movable` (non-copyable and non-movable):

[import ../example/copymovable.hpp]
[copy_movable_definition]

and build a generic factory function that returns a newly constructed value or a reference to an already
constructed object.

[import ../example/doc_move_return.cpp]
[move_return_example]

[*Caution]: When using this macro in a non-conforming or C++03
compilers, a move will be performed even if the C++11 standard does not allow it
(e.g. returning a static variable). The user is responsible for using this macro
only used to return local objects that met C++11 criteria. E.g.:

[c++]

   struct foo
   {
      copy_movable operator()() const
      {
         //ERROR! The Standard does not allow implicit move returns when the object to be returned 
         //does not met the criteria for elision of a copy operation (such as returning a static member data)
         //In C++03 compilers this will MOVE resources from cm
         //In C++11 compilers this will COPY resources from cm
         //so DON'T use use BOOST_MOVE_RET without care.
         return BOOST_MOVE_RET(copy_movable, cm);
      }

      static copy_movable cm;
   };


[*Note]: When returning a temporary object `BOOST_MOVE_REF` is not needed as copy ellision rules will work on
both C++03 and C++11 compilers.

[c++]

   //Note: no BOOST_MOVE_RET
   movable get_movable()
   {  return movable();  }

   copy_movable get_copy_movable()
   {  return copy_movable();  }

   copyable get_copyable()
   {  return copyable();  }


[endsect]

[section:move_iterator Move iterators]

[c++]

   template<class Iterator>
   class move_iterator;

   template<class It>
   move_iterator<It> make_move_iterator(const It &it);

[classref boost::move_iterator move_iterator] is an iterator adaptor with the
same behavior as the underlying iterator
except that its dereference operator implicitly converts the value returned by the
underlying iterator's dereference operator to a rvalue reference: `boost::move(*underlying_iterator)`
It is a read-once iterator, but can have up to random access traversal characteristics.

`move_iterator` is very useful because some generic algorithms and container insertion functions
can be called with move iterators to replace copying with moving. For example:

[import ../example/movable.hpp]
[movable_definition]

`movable` objects can be moved from one container to another using move iterators and insertion
and assignment operations.w

[import ../example/doc_move_iterator.cpp]
[move_iterator_example]

[endsect]

[section:move_inserters Move inserters]

Similar to standard insert iterators, it's possible to deal with move insertion in the same way
as writing into an array. A special kind of iterator adaptors, called move insert iterators, are
provided with this library. With regular iterator classes,

[c++]

   while (first != last) *result++ = *first++;

causes a range [first,last) to be copied into a range starting with result. The same code with
result being a move insert iterator will move insert corresponding elements into the container.
This device allows all of the copying algorithms in the library to work in the move insert mode
instead of the regular overwrite mode. This library offers 3 move insert iterators and their
helper functions:

[c++]

   // Note: C models Container
   template <typename C> 
   class back_move_insert_iterator;

   template <typename C>
   back_move_insert_iterator<C> back_move_inserter(C& x);

   template <typename C>
   class front_move_insert_iterator;

   template <typename C>
   front_move_insert_iterator<C> front_move_inserter(C& x);

   template <typename C>
   class move_insert_iterator;

   template <typename C>
   move_insert_iterator<C> move_inserter(C& x, typename C::iterator it);


A move insert iterator is constructed from a container and possibly one of its iterators pointing
to where insertion takes place if it is neither at the beginning nor at the end of the container.
Insert iterators satisfy the requirements of output iterators. `operator*` returns the move insert
iterator itself. The assignment `operator=(T& x)` is defined on insert iterators to allow writing
into them, it inserts x right before where the insert iterator is pointing. In other words, an
`insert iterator` is like a cursor pointing into the container where the insertion takes place.
`back_move_iterator` move inserts elements at the end of a container, `front_insert_iterator`
move inserts elements at the beginning of a container, and `move_insert_iterator` move inserts
elements where the iterator points to in a container. `back_move_inserter`, `front_move_inserter`,
and `move_inserter` are three functions making the insert iterators out of a container. Here's
an example of how to use them:

[import ../example/doc_move_inserter.cpp]
[move_inserter_example]

[endsect]

[section:move_algorithms Move algorithms]

The standard library offers several copy-based algorithms. Some of them, like `std::copy` or
`std::uninitialized_copy` are basic building blocks for containers and other data structures.
This library offers move-based functions for those purposes:

[c++]

  template<typename I, typename O> O move(I, I, O);
  template<typename I, typename O> O move_backward(I, I, O);
  template<typename I, typename F> F uninitialized_move(I, I, F);
  template<typename I, typename F> F uninitialized_copy_or_move(I, I, F);


The first 3 are move variations of their equivalent copy algorithms, but copy assignment and
copy construction are replaced with move assignment and construction. The last one has the
same behaviour as `std::uninitialized_copy` but since several standand library implementations
don't play very well with `move_iterator`s, this version is a portable version for those
willing to use move iterators.

[import ../example/doc_move_algorithms.cpp]
[move_algorithms_example]

[endsect]

[section:emulation_limitations Emulation limitations]

Like any emulation effort, the library has some limitations users should take in
care to achieve portable and efficient code when using the library with C++03 conformant compilers:

[section:emulation_limitations_base Initializing base classes]

When initializing base classes in move constructors, users must
cast the reference to a base class reference before moving it or just
use `BOOST_MOVE_BASE`. Example:

[c++]

   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
      : Base(boost::move(static_cast<Base&>(x)))
        //...

or

[c++]

   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
      : Base(BOOST_MOVE_BASE(Base, x))
        //...

If casting is not performed the emulation will not move construct
the base class, because no conversion is available from `BOOST_RV_REF(Derived)` to
`BOOST_RV_REF(Base)`. Without the cast or `BOOST_MOVE_BASE` we might obtain a compilation
error (for non-copyable types) or a less-efficient move constructor (for copyable types):

[c++]

   //If Derived is copyable, then Base is copy-constructed.
   //If not, a compilation error is issued
   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
      : Base(boost::move(x))
        //...

[endsect]

[section:template_parameters Template parameters for perfect forwarding]

The emulation can't deal with C++0x reference collapsing rules that allow perfect forwarding:

[c++]
   
   //C++0x
   template<class T>
   void forward_function(T &&t)
   {  inner_function(std::forward<T>(t); }

   //Wrong C++03 emulation
   template<class T>
   void forward_function(BOOST_RV_REF<T> t)
   {  inner_function(boost::forward<T>(t); }

In C++03 emulation BOOST_RV_REF doesn't catch any const rlvalues. For more details on
forwarding see [link move.construct_forwarding Constructor Forwarding] chapter.

[endsect]

[section:emulation_limitations_binding Binding of rvalue references to lvalues]

The 
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html first rvalue reference]
proposal allowed the binding of rvalue references to lvalues:

[c++]

   func(Type &&t);
   //....
   
   Type t;  //Allowed
   func(t)


Later, as explained in
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html ['Fixing a Safety Problem with Rvalue References]]
this behaviour was considered dangerous and eliminated this binding so that rvalue references adhere to the
principle of type-safe overloading: ['Every function must be type-safe in isolation, without regard to how it has been overloaded]

[*Boost.Move] can't emulate this type-safe overloading principle for C++03 compilers:

[c++]

   //Allowed by move emulation
   movable m;
   BOOST_RV_REF(movable) r = m;

[endsect]

[section:assignment_operator Assignment operator in classes derived from or holding copyable and movable types]

The macro [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE] needs to
define a copy constructor for `copyable_and_movable` taking a non-const parameter in C++03 compilers:

[c++]

   //Generated by BOOST_COPYABLE_AND_MOVABLE
   copyable_and_movable &operator=(copyable_and_movable&){/**/}

Since the non-const overload of the copy constructor is generated, compiler-generated
assignment operators for classes containing `copyable_and_movable`
will get the non-const copy constructor overload, which will surely surprise users:

[c++]

   class holder
   {
      copyable_and_movable c;
   };

   void func(const holder& h)
   {
      holder copy_h(h); //<--- ERROR: can't convert 'const holder&' to 'holder&'
      //Compiler-generated copy constructor is non-const:
      // holder& operator(holder &)
      //!!!
   }

This limitation forces the user to define a const version of the copy assignment,
in all classes holding copyable and movable classes which might be annoying in some cases.

An alternative is to implement a single `operator =()` for copyable and movable  classes
[@http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ using "pass by value" semantics]:

[c++]

   T& operator=(T x)    // x is a copy of the source; hard work already done
   {
      swap(*this, x);  // trade our resources for x's
      return *this;    // our (old) resources get destroyed with x
   }

However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources
(like previously allocated memory) when x is assigned from a lvalue.

[endsect]

[section:templated_assignment_operator Templated assignment operator in copyable and movable types]


[import ../example/doc_template_assign.cpp]

Given a movable and copyable class, if a templated assignment operator (*) is added:

[template_assign_example_foo_bar]

C++98 and C++11 compilers will behave different when assigning from a `[const] Foo` lvalue:

[template_assign_example_main]

This different behaviour is a side-effect of the move emulation that can't be easily avoided by
[*Boost.Move]. One workaround is to SFINAE-out the templated assignment operator with `disable_if`:

[c++]

   template<class U> // Modified templated assignment
   typename boost::disable_if<boost::is_same<U, Foo>, Foo&>::type
      operator=(const U& rhs)
   {  i = -rhs.i; return *this;  } //(2)


[endsect]

[endsect]

[section:how_the_library_works How the library works]

[*Boost.Move] is based on macros that are expanded to true rvalue references in C++0x compilers
and emulated rvalue reference classes and conversion operators in C++03 compilers.

In C++03 compilers [*Boost.Move] defines a class named `::boost::rv`:

[c++]

   template <class T>
   class rv : public T
   {
      rv();
      ~rv();
      rv(rv const&);
      void operator=(rv const&);
   };

which is convertible to the movable base class (usual C++ derived to base conversion). When users mark
their classes as [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] or
[macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE], these macros define conversion
operators to references to `::boost::rv`:

[c++]

   #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
      public:\
      operator ::boost::rv<TYPE>&() \
      {  return *static_cast< ::boost::rv<TYPE>* >(this);  }\
      operator const ::boost::rv<TYPE>&() const \
      {  return static_cast<const ::boost::rv<TYPE>* >(this);  }\
      private:\
      //More stuff...

[macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] also declares a
private copy constructor and assignment. [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE]
defines a non-const copy constructor `TYPE &operator=(TYPE&)` that forwards to a const version:

   #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
      public:\
      TYPE& operator=(TYPE &t)\
      {  this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\
      //More stuff...

In C++0x compilers `BOOST_COPYABLE_AND_MOVABLE` expands to nothing and `BOOST_MOVABLE_BUT_NOT_COPYABLE`
declares copy constructor and assigment operator private.

When users define the [macroref BOOST_RV_REF BOOST_RV_REF] overload of a copy constructor/assignment, in
C++0x compilers it is expanded to a rvalue reference (`T&&`) overload and in C++03 compilers it is expanded
to a `::boost::rv<T> &` overload:

[c++]

   #define BOOST_RV_REF(TYPE) ::boost::rv< TYPE >& \

When users define the [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] overload,
it is expanded to a usual copy assignment (`const T &`) overload in C++0x compilers and
to a `const ::boost::rv &` overload in C++03 compilers:

[c++]

   #define BOOST_COPY_ASSIGN_REF(TYPE) const ::boost::rv< TYPE >&
   
As seen, in [*Boost.Move] generates efficient and clean code for C++0x move
semantics, without modifying any resolution overload. For C++03 compilers
when overload resolution is performed these are the bindings:

* a) non-const rvalues (e.g.: temporaries), bind to `::boost::rv< TYPE >&`
* b) const rvalue and lvalues, bind to `const ::boost::rv< TYPE >&`
* c) non-const lvalues (e.g. non-const references) bind to `TYPE&`

The library does not define the equivalent of
[macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] for copy construction (say, `BOOST_COPY_CTOR_REF`)
because nearly all modern compilers implement RVO and this is much more efficient than any move emulation.
[funcref boost::move move] just casts `TYPE &` into `::boost::rv<TYPE> &`.

Here's an example that demostrates how different rlvalue objects bind to `::boost::rv` references in the
presence of three overloads and the conversion operators in C++03 compilers:

[import ../example/doc_how_works.cpp]
[how_works_example]

[endsect]


[section:thanks_to Thanks and credits]

Thanks to all that developed ideas for move emulation: the first emulation was based on Howard Hinnant
emulation code for `unique_ptr`, David Abrahams suggested the use of `class rv`,
and Klaus Triendl discovered how to bind const rlvalues using `class rv`.

Many thanks to all boosters that have tested, reviewed and improved the library.

Special thanks to:

* Orson Peters, author of [@https://github.com/orlp/pdqsort Pattern-defeating quicksort (pdqsort)].
* Andrey Astrelin, author of [@https://github.com/Mrrl/GrailSort Grail Sort].

[endsect]

[section:release_notes Release Notes]

[section:release_notes_boost_1_81 Boost 1.81 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/49 Git Issue #49: ['"clang-15 warnings about deprecated type traits intrinsics"]].

[endsect]

[section:release_notes_boost_1_79 Boost 1.79 Release]

*  The library now compiles without warnings with GCC's -Wcast-align=strict
*  Fixed bugs:
   *  [@https://github.com/boostorg/move/pull/46   Git Issue #46: ['"Include <algorithm> when BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE is defined"]].
   *  [@https://github.com/boostorg/move/issues/47 Git Issue #47: ['"MSVC C5243: 'member_function_ptr': using incomplete class can cause potential ODR violation ..."]].
   *  [@https://github.com/boostorg/move/issues/48 Git Issue #48: ['"MSVC warning C4643: Forward declaring 'nothrow_t' in namespace std is not permitted by the C++ Standard"]].

[endsect]

[section:release_notes_boost_1_78 Boost 1.78 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/45 Git Issue #45: ['"Sort/merge bugs that affect boost::container::flat_map"]].

[endsect]

[section:release_notes_boost_1_77 Boost 1.77 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/40 Git Issue #40: ['"Warning 4675 is not defined in MSVC"]].
   *  [@https://github.com/boostorg/move/issues/42 Git Issue #42: ['"<boost/move/unique_ptr.hpp> fails when BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE is set"]].

[endsect]

[section:release_notes_boost_1_76 Boost 1.76 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/35 Git Issue #35: ['"New nothrow move traits are incomplete"]].

[endsect]

[section:release_notes_boost_1_75 Boost 1.75 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/30 Git Issue #30: ['"(void) C-cast is a non-portable way of suppressing compiler warnings"]].

[endsect]

[section:release_notes_boost_1_73 Boost 1.73 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/28 Git Issue #28: ['"Warning C4624 on MSVC 2019"]].

[endsect]

[section:release_notes_boost_1_71 Boost 1.71 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/26 Git Issue #26: ['"Invalid iterator increment/decrement in the last iteration of adaptive_sort_combine_blocks"]].

[endsect]

[section:release_notes_boost_1_70 Boost 1.70 Release]

*  Removed support for deprecated GCC compilers.
*  Fixed bugs:
   *  [@https://github.com/boostorg/move/pull/23 Git Pull #23: ['"Add minimal cmake file"]].
   *  [@https://github.com/boostorg/move/issues/25 Git Issue #25: ['"adaptive_merge is broken for iterator_traits<RandIt>::size_type != std::size_t"]].

[endsect]

[section:release_notes_boost_1_69 Boost 1.69 Release]

*  Deprecated GCC < 4.3 and MSVC < 9.0 (Visual 2008) compilers.
*  Fixed bugs:
   *  [@https://github.com/boostorg/move/issues/15 Git Issue #19: ['"Compilation error with IBM xlC++ on AIX"]].

[endsect]

[section:release_notes_boost_1_67 Boost 1.67 Release]

*  Added pdqsort and heap_sort implementations, initially as a detail, they will be official in the future once better tested.

[endsect]

[section:release_notes_boost_1_66 Boost 1.66 Release]

*  Fixed bugs:
   *  [@https://github.com/boostorg/move/pull/14   Git Pull  #14: ['"Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x"]].
   *  [@https://github.com/boostorg/move/issues/15 Git Issue #15: ['"Incorrect merge in adaptive_merge when the number of unique items is limited"]].

[endsect]


[section:release_notes_boost_1_65 Boost 1.65 Release]

*  Fixed bug:
   *  [@https://github.com/boostorg/move/pull/11 Git Pull #11: ['"replace 'std::random_shuffle' by '::random_shuffle'"]].
   *  [@https://github.com/boostorg/move/pull/12 Git Pull #12: ['"Adds support for MSVC ARM64 target'"]].

[endsect]

[section:release_notes_boost_1_64 Boost 1.64 Release]

*  Fixed bug:
   *  [@https://svn.boost.org/trac/boost/ticket/12920 #12920 ['"movelib::unique_ptr: incorrect pointer type for nested array"]].

[endsect]

[section:release_notes_boost_1_62 Boost 1.62 Release]

*  Documented new limitations reported in Trac tickets
   [@https://svn.boost.org/trac/boost/ticket/12194 #12194 ['"Copy assignment on moveable and copyable classes uses wrong type"]] and
   [@https://svn.boost.org/trac/boost/ticket/12307 #12307 ['"Copy assignment from const ref handled differently in C++11/C++98"]].

[endsect]

[section:release_notes_boost_1_61 Boost 1.61 Release]

*  Experimental: asymptotically optimal bufferless merge and sort algorithms: [funcref boost::movelib::adaptive_merge adaptive_merge]
   and [funcref boost::movelib::adaptive_sort adaptive_sort].

*  Fixed bug:
   * [@https://svn.boost.org/trac/boost/ticket/11758 Trac #11758: ['"BOOST_MOVABLE_BUT_NOT_COPYABLE doesn't reset private access with rvalue ref version"]],

[endsect]

[section:release_notes_boost_1_60 Boost 1.60 Release]

*  Fixed bug:
   * [@https://svn.boost.org/trac/boost/ticket/11615 Trac #11615: ['"Boost.Move should use the qualified name for std::size_t in type_traits.hpp"]],

[endsect]

[section:release_notes_boost_1_59 Boost 1.59 Release]

*  Changed `unique_ptr`'s converting constructor taking the source by value in C++03 compilers to allow simple conversions
   from convertible types returned by value.
*  Fixed bug:
   * [@https://svn.boost.org/trac/boost/ticket/11229 Trac #11229: ['"vector incorrectly copies move-only objects using memcpy"]],
   * [@https://svn.boost.org/trac/boost/ticket/11510 Trac #11510: ['"unique_ptr: -Wshadow warning issued"]],

[endsect]

[section:release_notes_boost_1_58_00 Boost 1.58 Release]

*  Added [macroref BOOST_MOVE_BASE BOOST_MOVE_BASE] utility.
*  Added [funcref boost::adl_move_swap adl_move_swap] utility.
*  Reduced dependencies on other Boost libraries to make the library a bit more lightweight.
*  Fixed bugs:
   *  [@https://svn.boost.org/trac/boost/ticket/11044 Trac #11044: ['"boost::rv inherits off union, when such passed as template argument"]].

[endsect]

[section:release_notes_boost_1_57_00 Boost 1.57 Release]

*  Added `unique_ptr` smart pointer. Thanks to Howard Hinnant for his excellent unique_ptr emulation code and testsuite.
*  Added `move_if_noexcept` utility. Thanks to Antony Polukhin for the implementation.
*  Fixed bugs:
   *  [@https://svn.boost.org/trac/boost/ticket/9785 Trac #9785: ['"Compiler warning with intel icc in boost/move/core.hpp"]],
   *  [@https://svn.boost.org/trac/boost/ticket/10460 Trac #10460: ['"Compiler error due to looser throw specifier"]],
   *  [@https://github.com/boostorg/move/pull/3 Git Pull #3: ['"Don't delete copy constructor when rvalue references are disabled"]],

[endsect]
 
[section:release_notes_boost_1_56_00 Boost 1.56 Release]

*  Added [macroref BOOST_MOVE_RET BOOST_MOVE_RET].
*  Fixed bugs:
      *  [@https://svn.boost.org/trac/boost/ticket/9482 #9482: ['"MSVC macros not undefined in boost/move/detail/config_end.hpp"]],
      *  [@https://svn.boost.org/trac/boost/ticket/9045 #9045: ['"Wrong macro name on docs"]],
      *  [@https://svn.boost.org/trac/boost/ticket/8420 #8420: ['"move's is_convertible does not compile with aligned data"]].

[endsect]

[section:release_notes_boost_1_55_00 Boost 1.55 Release]

*  Fixed bugs  [@https://svn.boost.org/trac/boost/ticket/7952 #7952],
               [@https://svn.boost.org/trac/boost/ticket/8764 #8764],
               [@https://svn.boost.org/trac/boost/ticket/8765 #8765],
               [@https://svn.boost.org/trac/boost/ticket/8842 #8842],
               [@https://svn.boost.org/trac/boost/ticket/8979 #8979].

[endsect]


[section:release_notes_boost_1_54_00 Boost 1.54 Release]


*  Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7969 #7969],
              [@https://svn.boost.org/trac/boost/ticket/8231 #8231],
              [@https://svn.boost.org/trac/boost/ticket/8765 #8765].

[endsect]

[section:release_notes_boost_1_53_00 Boost 1.53 Release]

*  Better header segregation (bug
  [@https://svn.boost.org/trac/boost/ticket/6524 #6524]).
*  Small documentation fixes
*  Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.
*  Fixed [@https://svn.boost.org/trac/boost/ticket/7830 #7830],
         [@https://svn.boost.org/trac/boost/ticket/7832 #7832].

[endsect]

[section:release_notes_boost_1_51_00 Boost 1.51 Release]

*  Fixed bugs
  [@https://svn.boost.org/trac/boost/ticket/7095 #7095],
  [@https://svn.boost.org/trac/boost/ticket/7031 #7031].

[endsect]

[section:release_notes_boost_1_49_00 Boost 1.49 Release]

*  Fixed bugs
  [@https://svn.boost.org/trac/boost/ticket/6417 #6417],
  [@https://svn.boost.org/trac/boost/ticket/6183 #6183],
  [@https://svn.boost.org/trac/boost/ticket/6185 #6185],
  [@https://svn.boost.org/trac/boost/ticket/6395 #6395],
  [@https://svn.boost.org/trac/boost/ticket/6396 #6396],

[endsect]

[endsect]

[xinclude autodoc.xml]