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