• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2 / Copyright (c) 2008-2010 Ion Gaztanaga
3 /
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 /]
7[library Boost.Move
8    [quickbook 1.5]
9    [authors [Gaztanaga, Ion]]
10    [copyright 2008-2014 Ion Gaztanaga]
11    [id move]
12    [dirname move]
13    [purpose Move semantics]
14    [license
15        Distributed under the Boost Software License, Version 1.0.
16        (See accompanying file LICENSE_1_0.txt or copy at
17        [@http://www.boost.org/LICENSE_1_0.txt])
18    ]
19]
20
21[important To be able to use containers of movable-only values in C++03 mode you will need to use containers
22supporting move semantics, like [*Boost.Container] containers]
23
24[section:tested_compilers Tested compilers]
25
26[*Boost.Move] has been tested in the following compilers/platforms:
27
28*  Visual C++ >= 7.1.
29*  GCC >= 4.1.
30
31[warning GCC < 4.3 and MSVC < 9.0 are deprecated and will be removed in the next version.]
32
33[endsect]
34
35[section:what_is_boost_move What is Boost.Move?]
36
37Rvalue references are a major C++0x feature, enabling move semantics for C++ values. However, we
38don't need C++0x compilers to take advantage of move semanatics. [*Boost.Move] emulates C++0x
39move semantics in C++03 compilers and allows writing portable code that works optimally in C++03
40and C++0x compilers.
41
42[endsect]
43
44[section:introduction Introduction]
45
46[note
47
48  The first 3 chapters are the adapted from the article
49 [@http://www.artima.com/cppsource/rvalue.html ['A Brief Introduction to Rvalue References]]
50 by Howard E. Hinnant, Bjarne Stroustrup, and Bronek Kozicki
51
52]
53
54Copying can be expensive. For example, for vectors `v2=v1` typically involves a function call,
55a memory allocation, and a loop. This is of course acceptable where we actually need two copies of
56a vector, but in many cases, we don't: We often copy a `vector` from one place to another, just to
57proceed to overwrite the old copy. Consider:
58
59[c++]
60
61   template <class T> void swap(T& a, T& b)
62   {
63      T tmp(a);   // now we have two copies of a
64      a = b;      // now we have two copies of b
65      b = tmp;    // now we have two copies of tmp (aka a)
66   }
67
68But, we didn't want to have any copies of a or b, we just wanted to swap them. Let's try again:
69
70[c++]
71
72   template <class T> void swap(T& a, T& b)
73   {
74      T tmp(::boost::move(a));
75      a = ::boost::move(b);
76      b = ::boost::move(tmp);
77   }
78
79This `move()` gives its target the value of its argument, but is not obliged to preserve the value
80of its source. So, for a `vector`, `move()` could reasonably be expected to leave its argument as
81a zero-capacity vector to avoid having to copy all the elements. In other words, [*move is a potentially
82destructive copy].
83
84In this particular case, we could have optimized swap by a specialization. However, we can't
85specialize every function that copies a large object just before it deletes or overwrites it. That
86would be unmanageable.
87
88In C++0x, move semantics are implemented with the introduction of rvalue references. They allow us to
89implement `move()` without verbosity or runtime overhead. [*Boost.Move] is a library that offers tools
90to implement those move semantics not only in compilers with `rvalue references` but also in compilers
91conforming to C++03.
92
93[endsect]
94
95[section:implementing_movable_classes Implementing copyable and movable classes]
96
97[import ../example/doc_clone_ptr.cpp]
98
99[section:copyable_and_movable_cpp0x Copyable and movable classes in C++0x]
100
101Consider a simple handle class that owns a resource and also provides copy semantics
102(copy constructor and assignment). For example a `clone_ptr` might own a pointer, and call
103`clone()` on it for copying purposes:
104
105[c++]
106
107   template <class T>
108   class clone_ptr
109   {
110      private:
111      T* ptr;
112
113      public:
114      // construction
115      explicit clone_ptr(T* p = 0) : ptr(p) {}
116
117      // destruction
118      ~clone_ptr() { delete ptr; }
119
120      // copy semantics
121      clone_ptr(const clone_ptr& p)
122         : ptr(p.ptr ? p.ptr->clone() : 0) {}
123
124      clone_ptr& operator=(const clone_ptr& p)
125      {
126         if (this != &p)
127         {
128            T *p = p.ptr ? p.ptr->clone() : 0;
129            delete ptr;
130            ptr = p;
131         }
132         return *this;
133      }
134
135      // move semantics
136      clone_ptr(clone_ptr&& p)
137         : ptr(p.ptr) { p.ptr = 0; }
138
139      clone_ptr& operator=(clone_ptr&& p)
140      {
141         if(this != &p)
142         {
143            std::swap(ptr, p.ptr);
144            delete p.ptr;
145            p.ptr = 0;
146         }
147         return *this;
148      }
149
150      // Other operations...
151   };
152
153`clone_ptr` has expected copy constructor and assignment semantics, duplicating resources when copying.
154Note that copy constructing or assigning a `clone_ptr` is a relatively expensive operation:
155
156[copy_clone_ptr]
157
158`clone_ptr` is code that you might find in today's books on C++, except for the part marked as
159`move semantics`. That part is implemented in terms of C++0x `rvalue references`. You can find
160some good introduction and tutorials on rvalue references in these papers:
161
162*  [@http://www.artima.com/cppsource/rvalue.html ['A Brief Introduction to Rvalue References]]
163*  [@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]]
164
165When the source of the copy is known to be a `rvalue` (e.g.: a temporary object), one can avoid the
166potentially expensive `clone()` operation by pilfering source's pointer (no one will notice!). The move
167constructor above does exactly that, leaving the rvalue in a default constructed state. The move assignment
168operator simply does the same freeing old resources.
169
170Now when code tries to copy a rvalue `clone_ptr`, or if that code explicitly gives permission to
171consider the source of the copy a rvalue (using `boost::move`), the operation will execute much faster.
172
173[move_clone_ptr]
174
175[endsect]
176
177[section:copyable_and_movable_cpp03 Copyable and movable classes in portable syntax for both C++03 and C++0x compilers]
178
179Many aspects of move semantics can be emulated for compilers not supporting `rvalue references`
180and [*Boost.Move] offers tools for that purpose. With [*Boost.Move] we can write `clone_ptr`
181so that it will work both in compilers with rvalue references and those who conform to C++03.
182You just need to follow these simple steps:
183
184* Put the following macro in the [*private] section:
185  [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE(classname)]
186* Leave copy constructor as is.
187* Write a copy assignment taking the parameter as
188  [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF(classname)]
189* Write a move constructor and a move assignment taking the parameter as
190  [macroref BOOST_RV_REF BOOST_RV_REF(classname)]
191
192Let's see how are applied to `clone_ptr`:
193
194[clone_ptr_def]
195
196[endsect]
197
198[*Question]: What about types that don't own resources? (E.g. `std::complex`?)
199
200No work needs to be done in that case. The copy constructor is already optimal.
201
202[endsect]
203
204[section:composition_inheritance Composition or inheritance]
205
206For classes made up of other classes (via either composition or inheritance), the move constructor
207and move assignment can be easily coded using the `boost::move` function:
208
209[clone_ptr_base_derived]
210
211[important Due to limitations in the emulation code, a cast to `Base &` is needed before moving the base part in the move
212constructor and call Base's move constructor instead of the copy constructor.]
213
214Each subobject will now be treated individually, calling move to bind to the subobject's move
215constructors and move assignment operators. `Member` has move operations coded (just like
216our earlier `clone_ptr` example) which will completely avoid the tremendously more expensive
217copy operations:
218
219[clone_ptr_move_derived]
220
221Note above that the argument x is treated as a lvalue reference. That's why it is necessary to
222say `move(x)` instead of just x when passing down to the base class. This is a key safety feature of move
223semantics designed to prevent accidently moving twice from some named variable. All moves from
224lvalues occur explicitly.
225
226[endsect]
227
228[section:movable_only_classes Movable but Non-Copyable Types]
229
230Some types are not amenable to copy semantics but can still be made movable. For example:
231
232*  `unique_ptr` (non-shared, non-copyable ownership)
233*  A type representing a thread of execution
234*  A type representing a file descriptor
235
236By making such types movable (though still non-copyable) their utility is tremendously
237increased. Movable but non-copyable types can be returned by value from factory functions:
238
239[c++]
240
241   file_descriptor create_file(/* ... */);
242   //...
243   file_descriptor data_file;
244   //...
245   data_file = create_file(/* ... */);  // No copies!
246
247In the above example, the underlying file handle is passed from object to object, as long
248as the source `file_descriptor` is a rvalue. At all times, there is still only one underlying file
249handle, and only one `file_descriptor` owns it at a time.
250
251To write a movable but not copyable type in portable syntax, you need to follow these simple steps:
252
253* Put the following macro in the [*private] section:
254  [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE(classname)]
255* Write a move constructor and a move assignment taking the parameter as
256  [macroref BOOST_RV_REF BOOST_RV_REF(classname)]
257
258Here's the definition of `file descriptor` using portable syntax:
259
260[import ../example/doc_file_descriptor.cpp]
261[file_descriptor_def]
262
263[/
264 /Many standard algorithms benefit from moving elements of the sequence as opposed to
265 /copying them. This not only provides better performance (like the improved `swap`
266 /implementation described above), but also allows these algorithms to operate on movable
267 /but non-copyable types. For example the following code sorts a `vector<unique_ptr<T>>`
268 /based on comparing the pointed-to types:
269 /
270 /[c++]
271 /
272 /   struct indirect_less
273 /   {
274 /      template <class T>
275 /      bool operator()(const T& x, const T& y)
276 /         {return *x < *y;}
277 /   };
278 /   ...
279 /   std::vector<std::unique_ptr<A>> v;
280 /   ...
281 /   std::sort(v.begin(), v.end(), indirect_less());
282 /
283 /
284 /As sort moves the unique_ptr's around, it will use swap (which no longer requires Copyability)
285 /or move construction / move assignment. Thus during the entire algorithm, the invariant that
286 /each item is owned and referenced by one and only one smart pointer is maintained. If the
287 /algorithm were to attempt a copy (say by programming mistake) a compile time error would result.
288 /]
289
290[endsect]
291
292[section:move_and_containers Containers and move semantics]
293
294Movable but non-copyable types can be safely inserted into containers and
295movable and copyable types are more efficiently handled if those containers
296internally use move semantics instead of copy semantics.
297If the container needs to "change the location" of an element
298internally (e.g. vector reallocation) it will move the element instead of copying it.
299[*Boost.Container] containers are move-aware so you can write the following:
300
301[file_descriptor_example]
302
303[endsect]
304
305[section:construct_forwarding Constructor Forwarding]
306
307Consider writing a generic factory function that returns an object for a newly
308constructed generic type. Factory functions such as this are valuable for encapsulating
309and localizing the allocation of resources. Obviously, the factory function must accept
310exactly the same sets of arguments as the constructors of the type of objects constructed:
311
312[c++]
313
314   template<class T> T* factory_new()
315   {  return new T();  }
316
317   template<class T> T* factory_new(a1)
318   {  return new T(a1);  }
319
320   template<class T> T* factory_new(a1, a2)
321   {  return new T(a1, a2);  }
322
323Unfortunately, in C++03 the much bigger issue with this approach is that the N-argument case
324would require 2^N overloads, immediately discounting this as a general solution. Fortunately,
325most constructors take arguments by value, by const-reference or by rvalue reference. If these
326limitations are accepted, the forwarding emulation of a N-argument case requires just N overloads.
327This library makes this emulation easy with the help of `BOOST_FWD_REF` and
328`boost::forward`:
329
330[import ../example/doc_construct_forward.cpp]
331[construct_forward_example]
332
333Constructor forwarding comes in handy to implement placement insertion in containers with
334just N overloads if the implementor accepts the limitations of this type of forwarding for
335C++03 compilers. In compilers with rvalue references perfect forwarding is achieved.
336
337[endsect]
338
339[section:move_return Implicit Move when returning a local object]
340
341The C++ standard specifies situations where an implicit move operation is safe and the
342compiler can use it in cases were the (Named) Return Value Optimization) can't be used.
343The typical use case is when a function returns a named (non-temporary) object by value
344and the following code will perfectly compile in C++11:
345
346[c++]
347
348   //Even if movable can't be copied
349   //the compiler will call the move-constructor
350   //to generate the return value
351   //
352   //The compiler can also optimize out the move
353   //and directly construct the object 'm'
354   movable factory()
355   {
356      movable tmp;
357      m = ...
358      //(1) moved instead of copied
359      return tmp;
360   };
361
362   //Initialize object
363   movable m(factory());
364
365
366In compilers without rvalue references and some non-conforming compilers (such as Visual C++ 2010/2012)
367the line marked with `(1)` would trigger a compilation error because `movable` can't be copied. Using a explicit
368`::boost::move(tmp)` would workaround this limitation but it would code suboptimal in C++11 compilers
369(as the compile could not use (N)RVO to optimize-away the copy/move).
370
371[*Boost.Move] offers an additional macro called [macroref BOOST_MOVE_RET BOOST_MOVE_RET] that can be used to
372alleviate this problem obtaining portable move-on-return semantics. Let's use the previously presented
373movable-only `movable` class with classes `copyable` (copy-only type), `copy_movable` (can be copied and moved) and
374`non_copy_movable` (non-copyable and non-movable):
375
376[import ../example/copymovable.hpp]
377[copy_movable_definition]
378
379and build a generic factory function that returns a newly constructed value or a reference to an already
380constructed object.
381
382[import ../example/doc_move_return.cpp]
383[move_return_example]
384
385[*Caution]: When using this macro in a non-conforming or C++03
386compilers, a move will be performed even if the C++11 standard does not allow it
387(e.g. returning a static variable). The user is responsible for using this macro
388only used to return local objects that met C++11 criteria. E.g.:
389
390[c++]
391
392   struct foo
393   {
394      copy_movable operator()() const
395      {
396         //ERROR! The Standard does not allow implicit move returns when the object to be returned
397         //does not met the criteria for elision of a copy operation (such as returning a static member data)
398         //In C++03 compilers this will MOVE resources from cm
399         //In C++11 compilers this will COPY resources from cm
400         //so DON'T use use BOOST_MOVE_RET without care.
401         return BOOST_MOVE_RET(copy_movable, cm);
402      }
403
404      static copy_movable cm;
405   };
406
407
408[*Note]: When returning a temporary object `BOOST_MOVE_REF` is not needed as copy ellision rules will work on
409both C++03 and C++11 compilers.
410
411[c++]
412
413   //Note: no BOOST_MOVE_RET
414   movable get_movable()
415   {  return movable();  }
416
417   copy_movable get_copy_movable()
418   {  return copy_movable();  }
419
420   copyable get_copyable()
421   {  return copyable();  }
422
423
424[endsect]
425
426[section:move_iterator Move iterators]
427
428[c++]
429
430   template<class Iterator>
431   class move_iterator;
432
433   template<class It>
434   move_iterator<It> make_move_iterator(const It &it);
435
436[classref boost::move_iterator move_iterator] is an iterator adaptor with the
437same behavior as the underlying iterator
438except that its dereference operator implicitly converts the value returned by the
439underlying iterator's dereference operator to a rvalue reference: `boost::move(*underlying_iterator)`
440It is a read-once iterator, but can have up to random access traversal characteristics.
441
442`move_iterator` is very useful because some generic algorithms and container insertion functions
443can be called with move iterators to replace copying with moving. For example:
444
445[import ../example/movable.hpp]
446[movable_definition]
447
448`movable` objects can be moved from one container to another using move iterators and insertion
449and assignment operations.w
450
451[import ../example/doc_move_iterator.cpp]
452[move_iterator_example]
453
454[endsect]
455
456[section:move_inserters Move inserters]
457
458Similar to standard insert iterators, it's possible to deal with move insertion in the same way
459as writing into an array. A special kind of iterator adaptors, called move insert iterators, are
460provided with this library. With regular iterator classes,
461
462[c++]
463
464   while (first != last) *result++ = *first++;
465
466causes a range [first,last) to be copied into a range starting with result. The same code with
467result being a move insert iterator will move insert corresponding elements into the container.
468This device allows all of the copying algorithms in the library to work in the move insert mode
469instead of the regular overwrite mode. This library offers 3 move insert iterators and their
470helper functions:
471
472[c++]
473
474   // Note: C models Container
475   template <typename C>
476   class back_move_insert_iterator;
477
478   template <typename C>
479   back_move_insert_iterator<C> back_move_inserter(C& x);
480
481   template <typename C>
482   class front_move_insert_iterator;
483
484   template <typename C>
485   front_move_insert_iterator<C> front_move_inserter(C& x);
486
487   template <typename C>
488   class move_insert_iterator;
489
490   template <typename C>
491   move_insert_iterator<C> move_inserter(C& x, typename C::iterator it);
492
493
494A move insert iterator is constructed from a container and possibly one of its iterators pointing
495to where insertion takes place if it is neither at the beginning nor at the end of the container.
496Insert iterators satisfy the requirements of output iterators. `operator*` returns the move insert
497iterator itself. The assignment `operator=(T& x)` is defined on insert iterators to allow writing
498into them, it inserts x right before where the insert iterator is pointing. In other words, an
499`insert iterator` is like a cursor pointing into the container where the insertion takes place.
500`back_move_iterator` move inserts elements at the end of a container, `front_insert_iterator`
501move inserts elements at the beginning of a container, and `move_insert_iterator` move inserts
502elements where the iterator points to in a container. `back_move_inserter`, `front_move_inserter`,
503and `move_inserter` are three functions making the insert iterators out of a container. Here's
504an example of how to use them:
505
506[import ../example/doc_move_inserter.cpp]
507[move_inserter_example]
508
509[endsect]
510
511[section:move_algorithms Move algorithms]
512
513The standard library offers several copy-based algorithms. Some of them, like `std::copy` or
514`std::uninitialized_copy` are basic building blocks for containers and other data structures.
515This library offers move-based functions for those purposes:
516
517[c++]
518
519  template<typename I, typename O> O move(I, I, O);
520  template<typename I, typename O> O move_backward(I, I, O);
521  template<typename I, typename F> F uninitialized_move(I, I, F);
522  template<typename I, typename F> F uninitialized_copy_or_move(I, I, F);
523
524
525The first 3 are move variations of their equivalent copy algorithms, but copy assignment and
526copy construction are replaced with move assignment and construction. The last one has the
527same behaviour as `std::uninitialized_copy` but since several standand library implementations
528don't play very well with `move_iterator`s, this version is a portable version for those
529willing to use move iterators.
530
531[import ../example/doc_move_algorithms.cpp]
532[move_algorithms_example]
533
534[endsect]
535
536[section:emulation_limitations Emulation limitations]
537
538Like any emulation effort, the library has some limitations users should take in
539care to achieve portable and efficient code when using the library with C++03 conformant compilers:
540
541[section:emulation_limitations_base Initializing base classes]
542
543When initializing base classes in move constructors, users must
544cast the reference to a base class reference before moving it or just
545use `BOOST_MOVE_BASE`. Example:
546
547[c++]
548
549   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
550      : Base(boost::move(static_cast<Base&>(x)))
551        //...
552
553or
554
555[c++]
556
557   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
558      : Base(BOOST_MOVE_BASE(Base, x))
559        //...
560
561If casting is not performed the emulation will not move construct
562the base class, because no conversion is available from `BOOST_RV_REF(Derived)` to
563`BOOST_RV_REF(Base)`. Without the cast or `BOOST_MOVE_BASE` we might obtain a compilation
564error (for non-copyable types) or a less-efficient move constructor (for copyable types):
565
566[c++]
567
568   //If Derived is copyable, then Base is copy-constructed.
569   //If not, a compilation error is issued
570   Derived(BOOST_RV_REF(Derived) x)             // Move ctor
571      : Base(boost::move(x))
572        //...
573
574[endsect]
575
576[section:template_parameters Template parameters for perfect forwarding]
577
578The emulation can't deal with C++0x reference collapsing rules that allow perfect forwarding:
579
580[c++]
581
582   //C++0x
583   template<class T>
584   void forward_function(T &&t)
585   {  inner_function(std::forward<T>(t); }
586
587   //Wrong C++03 emulation
588   template<class T>
589   void forward_function(BOOST_RV_REF<T> t)
590   {  inner_function(boost::forward<T>(t); }
591
592In C++03 emulation BOOST_RV_REF doesn't catch any const rlvalues. For more details on
593forwarding see [link move.construct_forwarding Constructor Forwarding] chapter.
594
595[endsect]
596
597[section:emulation_limitations_binding Binding of rvalue references to lvalues]
598
599The
600[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html first rvalue reference]
601proposal allowed the binding of rvalue references to lvalues:
602
603[c++]
604
605   func(Type &&t);
606   //....
607
608   Type t;  //Allowed
609   func(t)
610
611
612Later, as explained in
613[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html ['Fixing a Safety Problem with Rvalue References]]
614this behaviour was considered dangerous and eliminated this binding so that rvalue references adhere to the
615principle of type-safe overloading: ['Every function must be type-safe in isolation, without regard to how it has been overloaded]
616
617[*Boost.Move] can't emulate this type-safe overloading principle for C++03 compilers:
618
619[c++]
620
621   //Allowed by move emulation
622   movable m;
623   BOOST_RV_REF(movable) r = m;
624
625[endsect]
626
627[section:assignment_operator Assignment operator in classes derived from or holding copyable and movable types]
628
629The macro [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE] needs to
630define a copy constructor for `copyable_and_movable` taking a non-const parameter in C++03 compilers:
631
632[c++]
633
634   //Generated by BOOST_COPYABLE_AND_MOVABLE
635   copyable_and_movable &operator=(copyable_and_movable&){/**/}
636
637Since the non-const overload of the copy constructor is generated, compiler-generated
638assignment operators for classes containing `copyable_and_movable`
639will get the non-const copy constructor overload, which will surely surprise users:
640
641[c++]
642
643   class holder
644   {
645      copyable_and_movable c;
646   };
647
648   void func(const holder& h)
649   {
650      holder copy_h(h); //<--- ERROR: can't convert 'const holder&' to 'holder&'
651      //Compiler-generated copy constructor is non-const:
652      // holder& operator(holder &)
653      //!!!
654   }
655
656This limitation forces the user to define a const version of the copy assignment,
657in all classes holding copyable and movable classes which might be annoying in some cases.
658
659An alternative is to implement a single `operator =()` for copyable and movable  classes
660[@http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ using "pass by value" semantics]:
661
662[c++]
663
664   T& operator=(T x)    // x is a copy of the source; hard work already done
665   {
666      swap(*this, x);  // trade our resources for x's
667      return *this;    // our (old) resources get destroyed with x
668   }
669
670However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources
671(like previously allocated memory) when x is assigned from a lvalue.
672
673[endsect]
674
675[section:templated_assignment_operator Templated assignment operator in copyable and movable types]
676
677
678[import ../example/doc_template_assign.cpp]
679
680Given a movable and copyable class, if a templated assignment operator (*) is added:
681
682[template_assign_example_foo_bar]
683
684C++98 and C++11 compilers will behave different when assigning from a `[const] Foo` lvalue:
685
686[template_assign_example_main]
687
688This different behaviour is a side-effect of the move emulation that can't be easily avoided by
689[*Boost.Move]. One workaround is to SFINAE-out the templated assignment operator with `disable_if`:
690
691[c++]
692
693   template<class U> // Modified templated assignment
694   typename boost::disable_if<boost::is_same<U, Foo>, Foo&>::type
695      operator=(const U& rhs)
696   {  i = -rhs.i; return *this;  } //(2)
697
698
699[endsect]
700
701[endsect]
702
703[section:how_the_library_works How the library works]
704
705[*Boost.Move] is based on macros that are expanded to true rvalue references in C++0x compilers
706and emulated rvalue reference classes and conversion operators in C++03 compilers.
707
708In C++03 compilers [*Boost.Move] defines a class named `::boost::rv`:
709
710[c++]
711
712   template <class T>
713   class rv : public T
714   {
715      rv();
716      ~rv();
717      rv(rv const&);
718      void operator=(rv const&);
719   };
720
721which is convertible to the movable base class (usual C++ derived to base conversion). When users mark
722their classes as [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] or
723[macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE], these macros define conversion
724operators to references to `::boost::rv`:
725
726[c++]
727
728   #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
729      public:\
730      operator ::boost::rv<TYPE>&() \
731      {  return *static_cast< ::boost::rv<TYPE>* >(this);  }\
732      operator const ::boost::rv<TYPE>&() const \
733      {  return static_cast<const ::boost::rv<TYPE>* >(this);  }\
734      private:\
735      //More stuff...
736
737[macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] also declares a
738private copy constructor and assignment. [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE]
739defines a non-const copy constructor `TYPE &operator=(TYPE&)` that forwards to a const version:
740
741   #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
742      public:\
743      TYPE& operator=(TYPE &t)\
744      {  this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\
745      //More stuff...
746
747In C++0x compilers `BOOST_COPYABLE_AND_MOVABLE` expands to nothing and `BOOST_MOVABLE_BUT_NOT_COPYABLE`
748declares copy constructor and assigment operator private.
749
750When users define the [macroref BOOST_RV_REF BOOST_RV_REF] overload of a copy constructor/assignment, in
751C++0x compilers it is expanded to a rvalue reference (`T&&`) overload and in C++03 compilers it is expanded
752to a `::boost::rv<T> &` overload:
753
754[c++]
755
756   #define BOOST_RV_REF(TYPE) ::boost::rv< TYPE >& \
757
758When users define the [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] overload,
759it is expanded to a usual copy assignment (`const T &`) overload in C++0x compilers and
760to a `const ::boost::rv &` overload in C++03 compilers:
761
762[c++]
763
764   #define BOOST_COPY_ASSIGN_REF(TYPE) const ::boost::rv< TYPE >&
765
766As seen, in [*Boost.Move] generates efficient and clean code for C++0x move
767semantics, without modifying any resolution overload. For C++03 compilers
768when overload resolution is performed these are the bindings:
769
770* a) non-const rvalues (e.g.: temporaries), bind to `::boost::rv< TYPE >&`
771* b) const rvalue and lvalues, bind to `const ::boost::rv< TYPE >&`
772* c) non-const lvalues (e.g. non-const references) bind to `TYPE&`
773
774The library does not define the equivalent of
775[macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] for copy construction (say, `BOOST_COPY_CTOR_REF`)
776because nearly all modern compilers implement RVO and this is much more efficient than any move emulation.
777[funcref boost::move move] just casts `TYPE &` into `::boost::rv<TYPE> &`.
778
779Here's an example that demostrates how different rlvalue objects bind to `::boost::rv` references in the
780presence of three overloads and the conversion operators in C++03 compilers:
781
782[import ../example/doc_how_works.cpp]
783[how_works_example]
784
785[endsect]
786
787
788[section:thanks_to Thanks and credits]
789
790Thanks to all that developed ideas for move emulation: the first emulation was based on Howard Hinnant
791emulation code for `unique_ptr`, David Abrahams suggested the use of `class rv`,
792and Klaus Triendl discovered how to bind const rlvalues using `class rv`.
793
794Many thanks to all boosters that have tested, reviewed and improved the library.
795
796Special thanks to:
797
798* Orson Peters, author of [@https://github.com/orlp/pdqsort Pattern-defeating quicksort (pdqsort)].
799* Andrey Astrelin, author of [@https://github.com/Mrrl/GrailSort Grail Sort].
800
801[endsect]
802
803[section:release_notes Release Notes]
804
805[section:release_notes_boost_1_73 Boost 1.73 Release]
806
807*  Fixed bugs:
808   *  [@https://github.com/boostorg/move/issues/28 Git Issue #28: ['"Warning C4624 on MSVC 2019"]].
809
810[endsect]
811
812[section:release_notes_boost_1_71 Boost 1.71 Release]
813
814*  Fixed bugs:
815   *  [@https://github.com/boostorg/move/issues/26 Git Issue #26: ['"Invalid iterator increment/decrement in the last iteration of adaptive_sort_combine_blocks"]].
816
817[endsect]
818
819[section:release_notes_boost_1_70 Boost 1.70 Release]
820
821*  Removed support for deprecated GCC compilers.
822*  Fixed bugs:
823   *  [@https://github.com/boostorg/move/pull/23 Git Pull #23: ['"Add minimal cmake file"]].
824   *  [@https://github.com/boostorg/move/issues/25 Git Issue #25: ['"adaptive_merge is broken for iterator_traits<RandIt>::size_type != std::size_t"]].
825
826[endsect]
827
828[section:release_notes_boost_1_69 Boost 1.69 Release]
829
830*  Deprecated GCC < 4.3 and MSVC < 9.0 (Visual 2008) compilers.
831*  Fixed bugs:
832   *  [@https://github.com/boostorg/move/issues/15 Git Issue #19: ['"Compilation error with IBM xlC++ on AIX"]].
833
834[endsect]
835
836[section:release_notes_boost_1_67 Boost 1.67 Release]
837
838*  Added pdqsort and heap_sort implementations, initially as a detail, they will be official in the future once better tested.
839
840[endsect]
841
842[section:release_notes_boost_1_66 Boost 1.66 Release]
843
844*  Fixed bugs:
845   *  [@https://github.com/boostorg/move/pull/14   Git Pull  #14: ['"Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x"]].
846   *  [@https://github.com/boostorg/move/issues/15 Git Issue #15: ['"Incorrect merge in adaptive_merge when the number of unique items is limited"]].
847
848[endsect]
849
850
851[section:release_notes_boost_1_65 Boost 1.65 Release]
852
853*  Fixed bug:
854   *  [@https://github.com/boostorg/move/pull/11 Git Pull #11: ['"replace 'std::random_shuffle' by '::random_shuffle'"]].
855   *  [@https://github.com/boostorg/move/pull/12 Git Pull #12: ['"Adds support for MSVC ARM64 target'"]].
856
857[endsect]
858
859[section:release_notes_boost_1_64 Boost 1.64 Release]
860
861*  Fixed bug:
862   *  [@https://svn.boost.org/trac/boost/ticket/12920 #12920 ['"movelib::unique_ptr: incorrect pointer type for nested array"]].
863
864[endsect]
865
866[section:release_notes_boost_1_62 Boost 1.62 Release]
867
868*  Documented new limitations reported in Trac tickets
869   [@https://svn.boost.org/trac/boost/ticket/12194 #12194 ['"Copy assignment on moveable and copyable classes uses wrong type"]] and
870   [@https://svn.boost.org/trac/boost/ticket/12307 #12307 ['"Copy assignment from const ref handled differently in C++11/C++98"]].
871
872[endsect]
873
874[section:release_notes_boost_1_61 Boost 1.61 Release]
875
876*  Experimental: asymptotically optimal bufferless merge and sort algorithms: [funcref boost::movelib::adaptive_merge adaptive_merge]
877   and [funcref boost::movelib::adaptive_sort adaptive_sort].
878
879*  Fixed bug:
880   * [@https://svn.boost.org/trac/boost/ticket/11758 Trac #11758: ['"BOOST_MOVABLE_BUT_NOT_COPYABLE doesn't reset private access with rvalue ref version"]],
881
882[endsect]
883
884[section:release_notes_boost_1_60 Boost 1.60 Release]
885
886*  Fixed bug:
887   * [@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"]],
888
889[endsect]
890
891[section:release_notes_boost_1_59 Boost 1.59 Release]
892
893*  Changed `unique_ptr`'s converting constructor taking the source by value in C++03 compilers to allow simple conversions
894   from convertible types returned by value.
895*  Fixed bug:
896   * [@https://svn.boost.org/trac/boost/ticket/11229 Trac #11229: ['"vector incorrectly copies move-only objects using memcpy"]],
897   * [@https://svn.boost.org/trac/boost/ticket/11510 Trac #11510: ['"unique_ptr: -Wshadow warning issued"]],
898
899[endsect]
900
901[section:release_notes_boost_1_58_00 Boost 1.58 Release]
902
903*  Added [macroref BOOST_MOVE_BASE BOOST_MOVE_BASE] utility.
904*  Added [funcref boost::adl_move_swap adl_move_swap] utility.
905*  Reduced dependencies on other Boost libraries to make the library a bit more lightweight.
906*  Fixed bugs:
907   *  [@https://svn.boost.org/trac/boost/ticket/11044 Trac #11044: ['"boost::rv inherits off union, when such passed as template argument"]].
908
909[endsect]
910
911[section:release_notes_boost_1_57_00 Boost 1.57 Release]
912
913*  Added `unique_ptr` smart pointer. Thanks to Howard Hinnant for his excellent unique_ptr emulation code and testsuite.
914*  Added `move_if_noexcept` utility. Thanks to Antony Polukhin for the implementation.
915*  Fixed bugs:
916   *  [@https://svn.boost.org/trac/boost/ticket/9785 Trac #9785: ['"Compiler warning with intel icc in boost/move/core.hpp"]],
917   *  [@https://svn.boost.org/trac/boost/ticket/10460 Trac #10460: ['"Compiler error due to looser throw specifier"]],
918   *  [@https://github.com/boostorg/move/pull/3 Git Pull #3: ['"Don't delete copy constructor when rvalue references are disabled"]],
919
920[endsect]
921
922[section:release_notes_boost_1_56_00 Boost 1.56 Release]
923
924*  Added [macroref BOOST_MOVE_RET BOOST_MOVE_RET].
925*  Fixed bugs:
926      *  [@https://svn.boost.org/trac/boost/ticket/9482 #9482: ['"MSVC macros not undefined in boost/move/detail/config_end.hpp"]],
927      *  [@https://svn.boost.org/trac/boost/ticket/9045 #9045: ['"Wrong macro name on docs"]],
928      *  [@https://svn.boost.org/trac/boost/ticket/8420 #8420: ['"move's is_convertible does not compile with aligned data"]].
929
930[endsect]
931
932[section:release_notes_boost_1_55_00 Boost 1.55 Release]
933
934*  Fixed bugs  [@https://svn.boost.org/trac/boost/ticket/7952 #7952],
935               [@https://svn.boost.org/trac/boost/ticket/8764 #8764],
936               [@https://svn.boost.org/trac/boost/ticket/8765 #8765],
937               [@https://svn.boost.org/trac/boost/ticket/8842 #8842],
938               [@https://svn.boost.org/trac/boost/ticket/8979 #8979].
939
940[endsect]
941
942
943[section:release_notes_boost_1_54_00 Boost 1.54 Release]
944
945
946*  Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7969 #7969],
947              [@https://svn.boost.org/trac/boost/ticket/8231 #8231],
948              [@https://svn.boost.org/trac/boost/ticket/8765 #8765].
949
950[endsect]
951
952[section:release_notes_boost_1_53_00 Boost 1.53 Release]
953
954*  Better header segregation (bug
955  [@https://svn.boost.org/trac/boost/ticket/6524 #6524]).
956*  Small documentation fixes
957*  Replaced deprecated BOOST_NO_XXXX with newer BOOST_NO_CXX11_XXX macros.
958*  Fixed [@https://svn.boost.org/trac/boost/ticket/7830 #7830],
959         [@https://svn.boost.org/trac/boost/ticket/7832 #7832].
960
961[endsect]
962
963[section:release_notes_boost_1_51_00 Boost 1.51 Release]
964
965*  Fixed bugs
966  [@https://svn.boost.org/trac/boost/ticket/7095 #7095],
967  [@https://svn.boost.org/trac/boost/ticket/7031 #7031].
968
969[endsect]
970
971[section:release_notes_boost_1_49_00 Boost 1.49 Release]
972
973*  Fixed bugs
974  [@https://svn.boost.org/trac/boost/ticket/6417 #6417],
975  [@https://svn.boost.org/trac/boost/ticket/6183 #6183],
976  [@https://svn.boost.org/trac/boost/ticket/6185 #6185],
977  [@https://svn.boost.org/trac/boost/ticket/6395 #6395],
978  [@https://svn.boost.org/trac/boost/ticket/6396 #6396],
979
980[endsect]
981
982[endsect]
983
984[xinclude autodoc.xml]
985