BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmf_movableref.h
Go to the documentation of this file.
1/// @file bslmf_movableref.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_movableref.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_MOVABLEREF
9#define INCLUDED_BSLMF_MOVABLEREF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_movableref bslmf_movableref
15/// @brief Provide a vocabulary type to enable move semantics.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_movableref
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_movableref-purpose"> Purpose</a>
25/// * <a href="#bslmf_movableref-classes"> Classes </a>
26/// * <a href="#bslmf_movableref-macros"> Macros </a>
27/// * <a href="#bslmf_movableref-description"> Description </a>
28/// * <a href="#bslmf_movableref-use-of-movableref<t_type>-parameters"> Use of MovableRef<t_TYPE> Parameters </a>
29/// * <a href="#bslmf_movableref-template-deduction-and-argument-forwarding"> Template Deduction and Argument Forwarding </a>
30/// * <a href="#bslmf_movableref-usage"> Usage </a>
31/// * <a href="#bslmf_movableref-example-1-difference-in-moving-trivial-and-non-trivial-fields"> Example 1: Difference In Moving Trivial And Non-trivial Fields </a>
32/// * <a href="#bslmf_movableref-example-2-basic-movableref<t>-usage"> Example 2: Basic MovableRef<T> Usage </a>
33///
34/// # Purpose {#bslmf_movableref-purpose}
35/// Provide a vocabulary type to enable move semantics.
36///
37/// # Classes {#bslmf_movableref-classes}
38///
39/// - bslmf::MovableRef: a template indicating that an object can be moved from
40/// - bslmf::MovableRefUtil: a namespace for functions dealing with movables
41///
42/// # Macros {#bslmf_movableref-macros}
43///
44/// - BSLMF_MOVABLEREF_DEDUCE(t_TYPE): movable ref of `t_TYPE` that is deducible
45/// - BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES: defined if MovableRef<T> is `T&&`
46///
47/// @see
48///
49/// # Description {#bslmf_movableref-description}
50/// This component provides a class template, `bslmf::MovableRef`
51/// used to convey the information that an object will not be used anymore so
52/// that its representation can be transferred elsewhere. In C++11 terminology
53/// an object represented by a `bslmf::MovableRef<T>` can be moved from. This
54/// component also provides a utility `struct` `bslmf::MovableRefUtil` that
55/// enables use of identical code for C++03 and C++11 to implement move
56/// semantics.
57///
58/// An object is /movable/ when it isn't being used in a way depending on its
59/// current representation after an operation on this object. For example, when
60/// passing a temporary object to a function the temporary object is movable: it
61/// can't be referred to other than in the function call. When objects are no
62/// longer be used their internal representation can be transferred to another
63/// object. Transferring the internal representation of an object to another
64/// object is called /moving an object/. The purpose of `bslmf::MovableRef<T>`
65/// is to indicate to a function that an object can be moved to another object.
66///
67/// With a C++11 implementation `bslmf::MovableRef<T>` is an alias template for
68/// `T&&`. With a C++03 implementation `bslmf::MovableRef<T>` is a class
69/// template providing l-value access to a movable object. The objective of
70/// this component is to provide a name for the concept of a movable object.
71/// Using a common name enables use of manual move semantics when using C++03.
72/// With C++11 additionally automatic move semantics is enabled resulting in
73/// moving objects known to the compiler to go out of scope, e.g., when passing
74/// a temporary object to a function or returning a local variable.
75///
76/// Using `bslmf::MovableRef<T>` to support movable types enables the
77/// implementation of move semantics that work with both C++03 and C++11 without
78/// conditional compilation of the user code. Only the implementation of the
79/// component @ref bslmf_movableref uses conditional compilation to select the
80/// appropriate implementation choice. For a C++11 implementation the use of
81/// `bslmf::MovableRef<T>` instead of `T&&` has the advantage that the `T` will
82/// not be deduced an the argument is known to be movable: when a function takes
83/// a `T&&` as argument with a deduced `T` the deduced type may be an l-value
84/// reference that isn't necessarily movable. When using `bslmf::MovableRef<T>`
85/// with C++11 the type will not be deduced and to turn an l-value into a
86/// movable object it is necessary to explicitly use `move()` at the call site.
87///
88/// For consistent use across different versions of the C++ standard, a few
89/// utility functions are provided in the utility class `bslmf::MovableRefUtil`.
90/// This class contains functions for moving and accessing objects. To enable
91/// an identical notation to access an object with C++11 (where
92/// `bslmf::MovableRef<T>` is just an l-value of type `T`) and with C++03 where
93/// `bslmf::MovableRef<T>` is a class type referencing an l-value of type `T`,
94/// the function template `bslmf::MovableRefUtil::access(r)` is provided.
95/// Similarly, the function `bslmf::MovableRefUtil::move(r)` provides
96/// identical notation for producing a movable reference in both C++03 and
97/// C++11.
98///
99/// In addition to the `move` and `access` functions, the
100/// `bslmf::MovableRefUtil` namespace provides 7 metafunctions that closely
101/// correspond to similar metafunctions in the C++11 standard library (and
102/// which defer to the standard library where available). These 7
103/// metafunctions and their C++11 equivalents are shown in the table below:
104/// @code
105/// +-----------------------------+------------------------------+
106/// | MovableRefUtil trait | C++11 standard trait |
107/// +-----------------------------+------------------------------+
108/// | IsLvalueReference<t_TYPE> | is_lvalue_reference<t_TYPE> |
109/// | IsMovableReference<t_TYPE> | is_rvalue_reference<t_TYPE> |
110/// | IsReference<t_TYPE> | is_reference<t_TYPE> |
111/// | RemoveReference<t_TYPE> | remove_reference<t_TYPE> |
112/// | AddLvalueReference<t_TYPE> | add_lvalue_reference<t_TYPE> |
113/// | AddMovableReference<t_TYPE> | add_rvalue_reference<t_TYPE> |
114/// | Decay<t_TYPE> | decay<t_TYPE> |
115/// +-----------------------------+------------------------------+
116/// @endcode
117/// Note that volatile-qualified `MovableRef` objects are non-sensical; unlike
118/// const objects they do not occur "naturally" as a result of argument passing
119/// or template-argument deduction and there would be no reason for a program
120/// to create one on purpose. In C++11, moreover, `volatile MovableRef<T>` is
121/// an alias for `T&& volatile`, which is not a valid type. The traits above,
122/// therefore, will fail to compile when instantiated with a volatile-qualified
123/// `MovableRef`. Note that, although `volatile MovableRef<T>` doesn't make
124/// sense, `MovableRef<volatile T>` is perfectly fine and are equivalent to
125/// `volatile T&&`.
126///
127/// ## Use of MovableRef<t_TYPE> Parameters {#bslmf_movableref-use-of-movableref<t_type>-parameters}
128///
129///
130/// There are a number of differences how `MovableRef<t_TYPE>` parameters are
131/// handled between C++03 and C++11 implementations. Due to the language
132/// differences there is no way to avoid these. This component enables use of
133/// move semantics in both C++03 and C++11 when done right. It doesn't try to
134/// make implementation of move semantics easier. Here are some notes to keep
135/// in mind when using this component:
136///
137/// 1. When using a `t_TYPE&&` in a context where `t_TYPE` is deduced, the
138/// resulting reference does normally *not* refer to an object that can be
139/// moved from! If `bslmf::MovableRef<t_TYPE>` would deduce the type when
140/// using a C++11 implementation the name would be rather misleading. Thus,
141/// the `t_TYPE` won't be deduced. When using a C++03 the type /can/ be
142/// deduced. However, a program depending on the `t_TYPE` being deduced from
143/// a `bslmf::MovableRef<t_TYPE>` will not compile with a C++11
144/// implementation.
145/// 2. Returning `MovableRef<t_TYPE>` (or `t_TYPE&&`) from a function is almost
146/// always wrong. In particular note that the same life-time issues apply to
147/// `MovableRef<t_TYPE>` as they do to references of objects: when returning
148/// a reference the object referred to cannot be on the stack, i.e.,
149/// returning a `MovableRef<t_TYPE>` referring to a local variable or a
150/// by-value function parameter is certainly wrong. Returning a
151/// `MovableRef<t_TYPE>` to a function parameter received as a reference type
152/// can be correct.
153/// 3. Using the argument of type `MovableRef<t_TYPE>` directly in a function
154/// typically results in incorrect behavior either when using C++03 or when
155/// using C++11. Instead, use these arguments together with
156/// `MovableRefUtil::move()`, `MovableRefUtil::access()`, or bind them to a
157/// non-`const` l-value reference.
158///
159/// The purpose of `access(x)` is to use the same notation for member access to
160/// `x` independent on whether it is an actual l-value reference or an
161/// `MovableRef<t_TYPE>`. For a concrete examples assume `x` is a
162/// `bsl::pair<A, B>`. When using a C++11 implementation
163/// `MovableRef<bsl::pair<A, B> >` is really just a `bsl::pair<A, B>&&` and the
164/// elements could be accessed using `x.first` and `x.second`. For a C++03
165/// implementation `MovableRef<bsl::pair<A, B> >` is a class type and `x.first`
166/// and `x.second` are not available. Instead, a reference to the pair needs to
167/// be obtained that could be done using `static_cast<bsl::pair<A, B >&>(x)` or
168/// by using a named variable. To unify the notation between the C++03 and
169/// C++11 implementation, simultaneously simplifying the C++03 use
170/// `MovableRefUtil::access(x)` can be used.
171///
172/// ## Template Deduction and Argument Forwarding {#bslmf_movableref-template-deduction-and-argument-forwarding}
173///
174///
175/// C++11 has two entirely different uses of the notation `T&&`:
176///
177/// 1. In contexts where the type `T` is not deduced `T&&` indicates an "rvalue
178/// reference". The notation implies that the resources held by the
179/// referenced object can be reused, typically because the lifetime of the
180/// object is about to end. An argument of type `T&&` can bind to an rvalue
181/// of type `T` or to an lvalue of type `T` that has been explicitly "moved"
182/// by the caller.
183/// 2. In contexts where the type `T` is deduced `T&&` indicates a "forwarding
184/// reference. The argument can be either an rvalue or an lvalue and the
185/// called function can preserve the value category (rvalue or lvalue) when
186/// forwarding the reference to another function.
187///
188/// The `bslmf::MovableRef<T>` emulation of `T&&` in C++03 works only for rvalue
189/// references, i.e., the first use of the notation. The C++11 definition of
190/// `bslmf::MovableRef<T>` is designed specifically to avoid deduction of `T`,
191/// thus preventing it from accidentally being used as a forwarding reference
192/// (which would have the wrong effect in C++03).
193///
194/// For contexts where it is desirable to deduce `T`, the
195/// `BSLMF_MOVABLEREF_DEDUCE` macro is provided. When invoked like
196/// `BSLMF_MOVABLEREF_DEDUCE(T)`, this macro expands to `bslmf::MovableRef<T>`
197/// in C++03, and a type alias to `T&&` for which substitution fails if `T&&`
198/// would be an lvalue reference in C++11 and later. In both cases, the type
199/// `T` is deducible, and substitution succeeds only if
200/// `BSLMF_MOVABLEREF_DEDUCE(T)` deduces a movable reference.
201///
202/// ## Usage {#bslmf_movableref-usage}
203///
204///
205/// This section illustrates intended usage of this component.
206///
207/// ### Example 1: Difference In Moving Trivial And Non-trivial Fields {#bslmf_movableref-example-1-difference-in-moving-trivial-and-non-trivial-fields}
208///
209///
210/// This example will show the definition of a couple simple move constructor
211/// that use `MovableRef`, and highlight the difference in how different data
212/// members are handled.
213///
214/// First, we create an minimal type similar to @ref string_view . For simplicity,
215/// we implement methods we are interested in directly in the class declaration
216/// and omit the rest:
217/// @code
218/// class StringView {
219/// // This class provides a view on a C-string.
220///
221/// // DATA
222/// const char *d_string_p; // pointer to the data
223///
224/// public:
225/// // CREATORS
226/// ...
227/// @endcode
228/// Here we define the move constructor for `StringView`. Note that the
229/// `original` here is either an object of type 'MovableRef<StringView> (in
230/// C++03), or an true r-value reference `StringView&&`, in C++11 or later.
231/// Because the type of `original` may be different when built with different
232/// language standards, we must take care to manipulate and access the value in
233/// a way that is syntactically valid irrespective of the language-standard
234/// being used. Here, we use `MovableRefUtil::access` to obtain `const &` to
235/// `original`, and we assign `original` to an l-value reference (`StringView&`)
236/// to set its value to 0. These are both operations that support the same
237/// syntax across language standards:
238/// @code
239/// StringView(bslmf::MovableRef<StringView> original)
240/// // Create a 'StringView' object that refers to the same c-string
241/// // as the specified 'original' object, and reset 'original' to not
242/// // refer to any string.
243/// : d_string_p(bslmf::MovableRefUtil::access(original).d_string_p)
244/// {
245/// StringView& reference = original;
246/// reference.d_string_p = 0;
247/// }
248///
249/// // ACCESSORS
250/// ...
251/// };
252/// @endcode
253/// Now, we define a second class, `Employee`, that contains both non-trivial
254/// `StringView` and a trivial integer field:
255/// @code
256/// class Employee {
257/// // This class represents an employee card.
258///
259/// // DATA
260/// StringView d_name; // employee name
261/// int d_id; // employee id
262///
263/// public:
264/// // CREATORS
265/// ...
266/// @endcode
267/// Here we define the move constructor for 'Employee". Note that for the data
268/// members of `original`, `d_id` is a fundamental type and we simply can access
269/// the value as a `const &`, but `d_name` is a `StringView`, so that we must
270/// use `MovableRefUtil::move` to move it in a language-standard neutral way:
271/// @code
272/// Employee(bslmf::MovableRef<Employee> original)
273/// // Create an 'Employee' object that has the same value as the
274/// // specified 'original' object, and reset 'original' to the default
275/// // state.
276/// : d_name(bslmf::MovableRefUtil::move(
277/// bslmf::MovableRefUtil::access(original).d_name))
278/// , d_id(bslmf::MovableRefUtil::access(original).d_id)
279/// {
280/// Employee& reference = original;
281/// reference.d_id = 0;
282/// }
283///
284/// // ACCESSORS
285/// ...
286/// };
287/// @endcode
288///
289/// ### Example 2: Basic MovableRef<T> Usage {#bslmf_movableref-example-2-basic-movableref<t>-usage}
290///
291///
292/// There are two sides of move semantics:
293///
294/// 1. Classes or class templates that are _move-enabled_, i.e., which can
295/// transfer their internal representation to another object in some
296/// situations. To become move-enabled a class needs to implement, at
297/// least, a move constructor. It should probably also implement a move
298/// assignment operator.
299/// 2. Users of a potentially move-enabled class may take advantage of moving
300/// objects by explicitly indicating that ownership of resources may be
301/// transferred. When using C++11 the compiler can automatically detect
302/// some situations where it is safe to move objects but this features is
303/// not available with C++03.
304///
305/// The usage example below demonstrate both use cases using a simplified
306/// version of `std::Vector<T>`. The class template is simplified to
307/// concentrate on the aspects relevant to `bslmf::MovableRef<T>`. Most of the
308/// operations are just normal implementations to create a container. The last
309/// two operations described are using move operations.
310///
311/// Assume we want to implement a class template similar to the standard library
312/// `vector` facility. First we declare the class template `Vector<t_TYPE>`.
313/// The definition of the this class template is rather straight forward, and
314/// for simplicity a few trivial operations are implemented directly in the
315/// class definition:
316/// @code
317/// template <class t_TYPE>
318/// class Vector
319/// {
320/// t_TYPE *d_begin;
321/// t_TYPE *d_end;
322/// t_TYPE *d_endBuffer;
323///
324/// static void swap(t_TYPE*& a, t_TYPE*& b);
325/// // Swap the specified pointers 'a' and 'b'.
326///
327/// public:
328/// Vector();
329/// // Create an empty Vector.
330///
331/// Vector(bslmf::MovableRef<Vector> other); // IMPLICIT
332/// // Create a Vector by transferring the content of the specified
333/// // 'other'.
334///
335/// Vector(const Vector& other);
336/// // Create a Vector by copying the content of the specified 'other'.
337///
338/// Vector& operator= (Vector other);
339/// // Assign a Vector by copying the content of the specified 'other'
340/// // and return a reference to this object. Note that 'other' is
341/// // passed by value to have the copy or move already be done, or
342/// // even elided. Within the body of the assignment operator the
343/// // content of 'this' and 'other' are simply swapped.
344///
345/// ~Vector();
346/// // Destroy the Vector's elements and release any allocated memory.
347///
348/// t_TYPE& operator[](int index) { return this->d_begin[index]; }
349/// // Return a reference to the object at the specified 'index'.
350///
351/// const t_TYPE& operator[](int index) const
352/// { return this->d_begin[index]; }
353/// // Return a reference to the object at the specified 'index'.
354///
355/// t_TYPE *begin() { return this->d_begin; }
356/// // Return a pointer to the first element.
357///
358/// const t_TYPE *begin() const { return this->d_begin; }
359/// // Return a pointer to the first element.
360///
361/// int capacity() const { return int(this->d_endBuffer - this->d_begin); }
362/// // Return the capacity of the Vector.
363///
364/// bool empty() const { return this->d_begin == this->d_end; }
365/// // Return 'true' if the Vector is empty and 'false' otherwise.
366///
367/// t_TYPE *end() { return this->d_end; }
368/// // Return a pointer to the end of the range.
369///
370/// const t_TYPE *end() const { return this->d_end; }
371/// // Return a pointer to the end of the range.
372///
373/// void push_back(const t_TYPE& value);
374/// // Append a copy of the specified 'value' to the Vector.
375///
376/// void push_back(bslmf::MovableRef<t_TYPE> value);
377/// // Append an object moving the specified 'value' to the new
378/// // location.
379///
380/// void reserve(int newCapacity);
381/// // Reserve enough capacity to fit at least as many elements as
382/// // specified by 'newCapacity'.
383///
384/// int size() const { return int(this->d_end - this->d_begin); }
385/// // Return the size of the object.
386///
387/// void swap(Vector& other);
388/// // Swap the content of the Vector with the specified 'other'.
389/// };
390/// @endcode
391/// The class stores pointers to the begin and the end of the elements as well
392/// as a pointer to the end of the allocated buffer. If there are no elements,
393/// null pointers are stored. There a number of accessors similar to the
394/// accessors used by `std::Vector<t_TYPE>`.
395///
396/// The default constructor creates an empty `Vector<t_TYPE>` by simply
397/// initializing all member pointers to be null pointers:
398/// @code
399/// template <class t_TYPE>
400/// Vector<t_TYPE>::Vector()
401/// : d_begin()
402/// , d_end()
403/// , d_endBuffer()
404/// {
405/// }
406/// @endcode
407/// To leverage already implemented functionality some of the member functions
408/// operate on a temporary `Vector<t_TYPE>` and move the result into place using
409/// the `swap()` member function that simply does a memberwise `swap()` (the
410/// function swapping pointers is implemented here to avoid any dependency on
411/// functions defined in another level):
412/// @code
413/// template <class t_TYPE>
414/// void Vector<t_TYPE>::swap(t_TYPE*& a, t_TYPE*& b)
415/// {
416/// t_TYPE *tmp = a;
417/// a = b;
418/// b = tmp;
419/// }
420/// template <class t_TYPE>
421/// void Vector<t_TYPE>::swap(Vector& other)
422/// {
423/// this->swap(this->d_begin, other.d_begin);
424/// this->swap(this->d_end, other.d_end);
425/// this->swap(this->d_endBuffer, other.d_endBuffer);
426/// }
427/// @endcode
428/// The member function `reserve()` arranges for the `Vector<t_TYPE>` to have
429/// enough capacity for the number of elements specified as argument. The
430/// function first creates an empty `Vector<t_TYPE>` called `tmp` and sets `tmp`
431/// up to have enough capacity by allocating sufficient memory and assigning the
432/// different members to point to the allocated buffer. The function then
433/// iterates over the elements of `this` and for each element it constructs a
434/// new element in `tmp`.
435/// @code
436/// template <class t_TYPE>
437/// void Vector<t_TYPE>::reserve(int newCapacity)
438/// {
439/// if (this->capacity() < newCapacity) {
440/// Vector tmp;
441/// int size = int(sizeof(t_TYPE) * newCapacity);
442/// tmp.d_begin = static_cast<t_TYPE*>(operator new(size));
443/// tmp.d_end = tmp.d_begin;
444/// tmp.d_endBuffer = tmp.d_begin + newCapacity;
445///
446/// for (t_TYPE* it = this->d_begin; it != this->d_end; ++it) {
447/// new (tmp.d_end) t_TYPE(*it);
448/// ++tmp.d_end;
449/// }
450/// this->swap(tmp);
451/// }
452/// }
453/// @endcode
454/// Any allocated data and constructed elements need to be release in the
455/// destructor. The destructor does so by calling the destructor of the
456/// elements in the buffer from back to front. Once the elements are destroyed
457/// the buffer is released:
458/// @code
459/// template <class t_TYPE>
460/// Vector<t_TYPE>::~Vector()
461/// {
462/// if (this->d_begin) {
463/// while (this->d_begin != this->d_end) {
464/// --this->d_end;
465/// this->d_end->~t_TYPE();
466/// }
467/// operator delete(this->d_begin);
468/// }
469/// }
470/// @endcode
471/// Using `reserve()` and constructing the elements it is straight forward to
472/// implement the copy constructor. First the member pointers are initialed to
473/// null. If `other` is empty there is nothing further to do as it is desirable
474/// to not allocate a buffer for an empty `Vector`. If there are elements to
475/// copy the buffer is set up by calling `reserve()` to create sufficient
476/// capacity. Once that is done elements are copied by iterating over the
477/// elements of `other` and constructing elements using placement new in the
478/// appropriate location.
479/// @code
480/// template <class t_TYPE>
481/// Vector<t_TYPE>::Vector(const Vector& other)
482/// : d_begin()
483/// , d_end()
484/// , d_endBuffer()
485/// {
486/// if (!other.empty()) {
487/// this->reserve(4 < other.size()? other.size(): 4);
488///
489/// assert(other.size() <= this->capacity());
490/// for (t_TYPE* it = other.d_begin; it != other.d_end; ++it) {
491/// new (this->d_end) t_TYPE(*it);
492/// ++this->d_end;
493/// }
494/// }
495/// }
496/// @endcode
497/// A simple copy assignment operator can be implemented in terms of copy/move
498/// constructors, `swap()`, and destructor (in a real implementation the copy
499/// assignment would probably try to use already allocated objects). In this
500/// implementation that argument is taken by value, i.e., the argument is
501/// already constructed using copy or move construction (which may have been
502/// elided), the content of `this` is swapped with the content of `other`
503/// leaving this in the desired state, and the destructor will release the
504/// former representation of `this` when `other` is destroyed':
505/// @code
506/// template <class t_TYPE>
507/// Vector<t_TYPE>& Vector<t_TYPE>::operator= (Vector other)
508/// {
509/// this->swap(other);
510/// return *this;
511/// }
512/// @endcode
513/// To complete the normal C++03 operations of `Vector<t_TYPE>` the only
514/// remaining member function is `push_back()`. This function calls `reserve()`
515/// to obtain more capacity if the current capacity is filled and then
516/// constructs the new element at the location pointed to by `d_end`:
517/// @code
518/// template <class t_TYPE>
519/// void Vector<t_TYPE>::push_back(const t_TYPE& value)
520/// {
521/// if (this->d_end == this->d_endBuffer) {
522/// this->reserve(this->size()? 2 * this->size() : 4);
523/// }
524/// assert(this->d_end != this->d_endBuffer);
525/// new(this->d_end) t_TYPE(value);
526/// ++this->d_end;
527/// }
528/// @endcode
529/// The first operation actually demonstrating the use of `MovableRef<t_TYPE>`
530/// is the move constructor:
531/// @code
532/// template <class t_TYPE>
533/// Vector<t_TYPE>::Vector(bslmf::MovableRef<Vector> other)
534/// : d_begin(bslmf::MovableRefUtil::access(other).d_begin)
535/// , d_end(bslmf::MovableRefUtil::access(other).d_end)
536/// , d_endBuffer(bslmf::MovableRefUtil::access(other).d_endBuffer)
537/// {
538/// Vector& reference(other);
539/// reference.d_begin = 0;
540/// reference.d_end = 0;
541/// reference.d_endBuffer = 0;
542/// }
543/// @endcode
544/// This constructor gets an `MovableRef<Vector<t_TYPE> >` passed as argument
545/// that indicates that the referenced objects can be modified as long as it is
546/// left in a state meeting the class invariants. The implementation of this
547/// constructor first copies the `d_begin`, `d_end`, and `d_capacity` members of
548/// `other`. Since `other` is either an object of type
549/// `MovableRef<Vector<t_TYPE> >` (when compiling using a C++03 compiler) or an
550/// r-value reference `Vector<t_TYPE>&&` the members are accessed using
551/// `MovableRefUtil::access(other)` to get a reference to a `Vector<t_TYPE>`.
552/// Within the body of the constructor an l-value reference is obtained either
553/// via the conversion operator of `MovableRef<T>` or directly as `other` is
554/// just an l-value when compiling with a C++11 compiler. This reference is
555/// used to set the pointer members of the object referenced by `other` to `0`
556/// completing the move of the content to the object under construction.
557///
558/// Finally, a move version of `push_back()` is provided: it takes an
559/// `MovableRef<t_TYPE>` as argument. The type of this argument indicates that
560/// the state can be transferred and after arranging enough capacity in the
561/// `Vector<t_TYPE>` object a new element is move constructed at the position
562/// `d_end`:
563/// @code
564/// template <class t_TYPE>
565/// void Vector<t_TYPE>::push_back(bslmf::MovableRef<t_TYPE> value)
566/// {
567/// if (this->d_end == this->d_endBuffer) {
568/// this->reserve(this->size()? int(1.5 * this->size()): 4);
569/// }
570/// assert(this->d_end != this->d_endBuffer);
571/// new(this->d_end) t_TYPE(bslmf::MovableRefUtil::move(value));
572/// ++this->d_end;
573/// }
574/// @endcode
575/// Note that this implementation of `push_back()` uses
576/// `bslmf::MovableRefUtil::move(value)` to move the argument. For a C++03
577/// implementation the argument would be moved even when using `value` directly
578/// because the type of `value` stays `bslmf::MovableRef<t_TYPE>`. However, for
579/// a C++11 implementation the argument `value` is an l-value and using it
580/// directly would result in a copy.
581///
582/// To demonstrate the newly created `Vector<t_TYPE>` class in action, first a
583/// `Vector<int>` is created and filled with a few elements:
584/// @code
585/// Vector<int> vector0;
586/// for (int i = 0; i != 5; ++i) {
587/// vector0.push_back(i);
588/// }
589/// for (int i = 0; i != 5; ++i) {
590/// assert(vector0[i] == i);
591/// }
592/// @endcode
593/// To verify that copying of `Vector<t_TYPE>` objects works, a copy is created:
594/// @code
595/// Vector<int> vector1(vector0);
596/// assert(vector1.size() == 5);
597/// assert(vector1.size() == vector0.size());
598/// for (int i = 0; i != vector1.size(); ++i) {
599/// assert(vector1[i] == i);
600/// assert(vector1[i] == vector0[i]);
601/// }
602/// @endcode
603/// When using moving this `vector0` to a new location the representation of the
604/// new object should use the original `begin()`:
605/// @code
606/// const int *first = vector0.begin();
607/// Vector<int> vector2(bslmf::MovableRefUtil::move(vector0));
608/// assert(first == vector2.begin());
609/// @endcode
610/// When create a `Vector<Vector<int> >` and using `push_back()` on this object
611/// with `vector2` a copy should be inserted:
612/// @code
613/// Vector<Vector<int> > vVector;
614/// vVector.push_back(vector2); // copy
615/// assert(vector2.size() == 5);
616/// assert(vVector.size() == 1);
617/// assert(vVector[0].size() == vector2.size());
618/// assert(vVector[0].begin() != first);
619/// for (int i = 0; i != 5; ++i) {
620/// assert(vVector[0][i] == i);
621/// assert(vector2[i] == i);
622/// }
623/// @endcode
624/// When adding another element by moving `vector2` the `begin()` of the newly
625/// inserted element will be the same as `first`, i.e., the representation is
626/// transferred:
627/// @code
628/// vVector.push_back(bslmf::MovableRefUtil::move(vector2)); // move
629/// assert(vVector.size() == 2);
630/// assert(vVector[1].begin() == first);
631/// assert(vVector[1].size() == 5);
632/// @endcode
633/// Compiling this code with both C++03 and C++11 compilers shows that there is
634/// no need for conditional compilation in when using `MovableRef<t_TYPE>` while
635/// move semantics is enabled in both modes.
636/// ----------------------------------------------------------------------------
637/// @}
638/** @} */
639/** @} */
640
641/** @addtogroup bsl
642 * @{
643 */
644/** @addtogroup bslmf
645 * @{
646 */
647/** @addtogroup bslmf_movableref
648 * @{
649 */
650
651#include <bslscm_version.h>
652
655#include <bslmf_decay.h>
656#include <bslmf_enableif.h>
660#include <bslmf_isreference.h>
663
664#include <bsls_assert.h>
666#include <bsls_keyword.h>
667#include <bsls_platform.h>
668#include <bsls_util.h>
669
670#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
671 defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES)
672#define BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
673// This macro indicates whether the component uses C++11 r-value references to
674// implement 'bslmf::MovableRef<t_TYPE>'. It will evaluate to 'false' for
675// C++03 implementations and to 'true' for proper C++11 implementations. For
676// partial C++11 implementations it may evaluate to 'false' because both
677// r-value reference and alias templates need to be supported.
678#endif
679
680#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
681/// This macro expands to a movable reference to `__VA_ARGS__` for which the
682/// arguments are deducible in all language versions. Note that the
683/// argument list of this macro is variadic in order to support deducing
684/// template arguments, e.g., this macro supports uses like
685/// `BSLMF_MOVABLEREF_DEDUCE(bsl::pair<T1, T2>)` for which the types `T1`
686/// and `T2` are deducible, even though the macro argument contains a comma.
687# define BSLMF_MOVABLEREF_DEDUCE(...) \
688 ::BloombergLP::bslmf::MovableRef_Deduced<__VA_ARGS__>
689#else
690# define BSLMF_MOVABLEREF_DEDUCE(...) \
691 ::BloombergLP::bslmf::MovableRef<__VA_ARGS__>
692#endif
693
694
695namespace bslmf {
696
697struct MovableRefUtil;
698 // forward declaration
699
700/// forward declaration
701template <class t_TYPE>
702struct MovableRefUtil_AddLvalueReference;
703
704/// forward declaration
705template <class t_TYPE>
706struct MovableRefUtil_AddMovableReference;
707
708/// forward declaration
709template <class t_TYPE>
710struct MovableRefUtil_Decay;
711
712/// forward declaration
713template <class t_TYPE>
714struct MovableRefUtil_PropertyTraits;
715
716/// forward declaration
717template <class t_TYPE>
718struct MovableRefUtil_RemoveReference;
719
720#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
721
722/// forward declaration
723template <class t_TYPE>
724struct MovableRef_Helper;
725
726#endif
727
728 // ===============
729 // type MovableRef
730 // ===============
731
732#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
733
734/// The alias template `MovableRef<t_TYPE>` yields an r-value reference of
735/// type `t_TYPE&&`.
736template <class t_TYPE>
737using MovableRef = typename MovableRef_Helper<t_TYPE>::type;
738
739#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
740
741/// The class template `MovableRef<t_TYPE>` provides a reference to a
742/// movable object of type `t_TYPE`. Put differently, a function receiving
743/// an object this class template can transfer (move) the representation to
744/// a different object and leave the referenced object in an unspecified,
745/// although valid (i.e., it obeys all class invariants), state. With C++11
746/// an r-value reference (`t_TYPE&&`) is used to represent the same
747/// semantics.
748///
749/// See @ref bslmf_movableref
750template <class t_TYPE>
752
753 // DATA
754 t_TYPE *d_pointer;
755
756 // PRIVATE CREATORS
757
758 /// Create an `MovableRef<t_TYPE>` object referencing the object pointed
759 /// to by the specified `pointer`. The behavior is undefined if
760 /// `pointer` does not point to an object. This constructor is private
761 /// because a C++11 r-value reference cannot be created like this. For
762 /// information on how to create objects of type `MovableRef<t_TYPE>`
763 /// see `MovableRefUtil::move()`.
764 explicit MovableRef(t_TYPE *pointer);
765
766 // FRIENDS
767 friend struct MovableRefUtil;
768
769 public:
770 // ACCESSORS
771
772 /// Return a reference to the referenced object. In contexts where a
773 /// reference to an object of type `t_TYPE` is needed, a
774 /// `MovableRef<t_TYPE>` behaves like such a reference. For information
775 /// on how to access the reference in contexts where no conversion can
776 /// be used see `MovableRefUtil::access()`.
777 operator t_TYPE&() const;
778};
779
780#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
781
782 // =====================
783 // struct MovableRefUtil
784 // =====================
785
786/// This `struct` provides a collection of utility functions operating on
787/// objects of type `MovableRef<t_TYPE>`. The primary use of these
788/// utilities to create a consistent notation for using the C++03
789/// `MovableRef<t_TYPE>` objects and the C++11 `t_TYPE&&` r-value
790/// references.
792
793 public:
794 // TYPES
795
796 /// This `struct` template provides a Boolean metafunction that inherits
797 /// from `bsl::true_type` if the specified `t_TYPE` is an lvalue
798 /// reference, and inherits from `bsl::false_type` otherwise.
799 template <class t_TYPE>
801 : MovableRefUtil_PropertyTraits<t_TYPE>::IsLvalueReference {
802 };
803
804 /// This `struct` template provides a Boolean metafunction that inherits
805 /// from `bsl::true_type` if the specified `t_TYPE` is a specialization
806 /// of `MovableRef`, and inherits from `bsl::false_type` otherwise.
807 template <class t_TYPE>
809 : MovableRefUtil_PropertyTraits<t_TYPE>::IsMovableReference {
810 };
811
812 /// This `struct` template provides a Boolean metafunction that inherits
813 /// from `bsl::true_type` if the specified `t_TYPE` is either an lvalue
814 /// reference or a specialization of `MovableRef`, and inherits from
815 /// `bsl::false_type` otherwise.
816 template <class t_TYPE>
817 struct IsReference : MovableRefUtil_PropertyTraits<t_TYPE>::IsReference {
818 };
819
820 /// This `struct` template provides a metafunction that, if the
821 /// specified `t_TYPE` is a reference type, defines a nested `type`
822 /// typedef of the type to which `t_TYPE` refers, and defines a nested
823 /// `type` typedef of `t_TYPE` otherwise.
824 template <class t_TYPE>
827
828 /// This `struct` template provides a metafunction that defines a nested
829 /// `type` typedef that is an lvalue reference to `t_TYPE`. If `t_TYPE`
830 /// is already an `lvalue` reference, then `type` is `t_TYPE`.
831 /// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`.
832 /// This transformation reflects the semantics of _reference collapsing_
833 /// in section [dec.ref] of the standard.
834 template <class t_TYPE>
837
838 /// This `struct` template provides a metafunction that defines a nested
839 /// `type` typedef that, if `t_TYPE` is not a reference type, is
840 /// `MovableRef<t_TYPE>`. Otherwise, if `t_TYPE` is a specialization of
841 /// `MovableRef`, `type` is the same as `t_TYPE`. Otherwise, `type` is
842 /// `t_TYPE&`. This transformation reflects the semantics of
843 /// _reference collapsing_ in section [dec.ref] of the standard.
844 template <class t_TYPE>
847
848 /// This `struct` template provides a metafunction that defines a nested
849 /// `type` typedef that applies lvalue-to-rvalue, array-to-pointer, and
850 /// function-to-pointer conversions that occur when an lvalue of type
851 /// `t_TYPE` is used as an rvalue, and also removes `const`, `volatile`,
852 /// and reference qualifiers from class types in order to model by-value
853 /// argument passing. For the purpose of this type trait,
854 /// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
855 ///
856 /// Formally, let `U` be
857 /// `MovableRefUtil::RemoveReference<t_TYPE>::type`. If
858 /// `bsl::is_array<U>::value` is true, the member typedef `type` is
859 /// `bsl::remove_extent<U>::type *`. If `bsl::is_function<U>::value` is
860 /// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
861 /// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
862 template <class t_TYPE>
863 struct Decay : MovableRefUtil_Decay<t_TYPE> {
864 };
865
866 // CLASS METHODS
867#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
868 template <class t_TYPE>
869 static typename bsl::remove_reference<t_TYPE>::type& access(
870 t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT;
871#else
872 template <class t_TYPE>
873 static t_TYPE& access(t_TYPE& ref) BSLS_KEYWORD_NOEXCEPT;
874 template <class t_TYPE>
876#endif
877 // Return an lvalue reference to the object referenced by the specified
878 // 'ref' object. This function is used to provide a uniform interface to
879 // members of an object reference by 'ref', regardless of whether 'ref' is
880 // an 'MovableRef' or lvalue reference and whether the compiler supports
881 // C++11 rvalue references. This function is unnecessary (but allowed)
882 // when simply converting 'ref' to 't_TYPE&'.
883 //
884 // Please see the component-level documentation for more information on
885 // this function.
886
887#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
888 template <class t_TYPE>
891 move(t_TYPE&& reference) BSLS_KEYWORD_NOEXCEPT;
892#else
893 template <class t_TYPE>
894 static MovableRef<t_TYPE> move(t_TYPE& reference) BSLS_KEYWORD_NOEXCEPT;
895 template <class t_TYPE>
898#endif
899 // Return a movable reference to the object referred to by the specified
900 // 'reference'. Note that the C++03 implementation of this function
901 // behaves like a factory for 'MovableRef<t_TYPE>' objects. The C++11
902 // implementation of this function behaves exactly like 'std::move(value)'
903 // applied to lvalues.
904
905 /// Return a const-qualified reference to the specified `lvalue`. This
906 /// function is selected by overload resolution if the move constructor
907 /// for `t_TYPE` might throw an exception. Constructing a `t_TYPE`
908 /// object from the result will result in the copy constructor being
909 /// invoked rather than the (unsafe) move constructor.
910 template <class t_TYPE>
911 static typename bsl::enable_if<
914 const t_TYPE&>::type
916 {
917 // The implementation is placed here in the class definition to work
918 // around a Microsoft C++ compiler (version 16) bug where the
919 // definition cannot be matched to the declaration when an 'enable_if'
920 // is used.
921 return lvalue;
922 }
923
924 /// Return a movable reference to the specified `lvalue`. This function
925 /// is selected by overload resolution if the move constructor for
926 /// `t_TYPE` is nothrow-move-constructible. Constructing a `t_TYPE`
927 /// object from the result will result in the (safe) move constructor
928 /// being invoked. Note that that the
929 /// `bsl::is_nothrow_move_constructible` trait can be customized in
930 /// C++03 mode to indicate that a type is nothrow-move-constructible.
931 template <class t_TYPE>
932 static typename bsl::enable_if<
935 MovableRef<t_TYPE> >::type
937 {
938 // The implementation is placed here in the class definition to work
939 // around a Microsoft C++ compiler (version 16) bug where the
940 // definition cannot be matched to the declaration when an 'enable_if'
941 // is used.
942#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
943 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(
944 lvalue);
945#else
947#endif
948 }
949};
950
951#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
952
953 // ========================
954 // struct MovableRef_Helper
955 // ========================
956
957/// The class template `MovableRef_Helper` just defines a nested type
958/// `type` that is used by an alias template. Using this indirection the
959/// template argument of the alias template is prevented from being deduced.
960template <class t_TYPE>
961struct MovableRef_Helper {
962
963 public:
964 // TYPES
965
966 /// The type `type` defined to be an r-value reference to the argument
967 /// type of 'MovableRef_Helper.
968 using type = t_TYPE&&;
969};
970
971 // =======================
972 // type MovableRef_Deduced
973 // =======================
974
975/// This component-private alias template names the type `t_TYPE&&` if and
976/// only if the specified `t_TYPE` is not an lvalue reference.
977template <class t_TYPE,
979 int>::type = 0>
980using MovableRef_Deduced = t_TYPE&&;
981
982#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
983
984// ============================================================================
985// INLINE DEFINITIONS
986// ============================================================================
987
988 // ----------------
989 // class MovableRef
990 // ----------------
991
992#ifndef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
993
994// CREATORS
995template <class t_TYPE>
996inline
997MovableRef<t_TYPE>::MovableRef(t_TYPE *pointer)
998: d_pointer(pointer)
999{
1000 BSLS_ASSERT(0 != pointer);
1001}
1002
1003// ACCESSORS
1004template <class t_TYPE>
1005inline
1007{
1008 return *d_pointer;
1009}
1010
1011#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1012
1013 // ---------------------
1014 // struct MovableRefUtil
1015 // ---------------------
1016
1017#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1018
1019// CLASS METHODS
1020template <class t_TYPE>
1021inline
1022typename bsl::remove_reference<t_TYPE>::type& MovableRefUtil::access(
1023 t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT
1024{
1025 return ref;
1026}
1027
1028#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1029
1030template <class t_TYPE>
1031inline
1033{
1034 return ref;
1035}
1036
1037template <class t_TYPE>
1038inline
1040{
1041 return ref;
1042}
1043
1044#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1045
1046#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1047
1048template <class t_TYPE>
1049inline
1052{
1053 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(rvalue);
1054}
1055
1056#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1057
1058template <class t_TYPE>
1059inline
1064
1065template <class t_TYPE>
1066inline
1072
1073#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1074
1075 // ------------------------------------
1076 // struct MovableRefUtil_PropertyTraits
1077 // ------------------------------------
1078
1079#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1080
1081/// Component-private class: do not use. Define Boolean-valued
1082/// movable-reference traits for the specified `t_TYPE`.
1083template <class t_TYPE>
1085
1086 // TYPES
1090};
1091
1092#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1093
1094/// Component-private class: do not use. Define Boolean-valued
1095/// movable-reference traits for rvalues of the specified `t_TYPE`.
1096template <class t_TYPE>
1103
1104/// Component-private class: do not use. Define Boolean-valued
1105/// movable-reference traits for lvalues of the specified `t_TYPE`.
1106template <class t_TYPE>
1113
1114/// Component-private class: do not use. Define Boolean-valued
1115/// movable-reference traits for movable references to the specified
1116/// `t_TYPE`.
1117template <class t_TYPE>
1124
1125template <class t_TYPE>
1129
1130template <class t_TYPE>
1132: MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {
1133};
1134
1135template <class t_TYPE>
1139
1140template <class t_TYPE>
1141struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE> >;
1142 // This partial 'struct' template specialization is not defined.
1143
1144template <class t_TYPE>
1145struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE>&>;
1146 // This partial 'struct' template specialization is not defined.
1147
1148template <class t_TYPE>
1149struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE> >;
1150 // This partial 'struct' template specialization is not defined.
1151
1152template <class t_TYPE>
1153struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE>&>;
1154 // This partial 'struct' template specialization is not defined.
1155
1156#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1157
1158 // -------------------------------------
1159 // struct MovableRefUtil_RemoveReference
1160 // -------------------------------------
1161
1162#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1163
1164/// This component-private `struct` template provides a metafunction that,
1165/// if the specified `t_TYPE` is a reference type, defines a nested `type`
1166/// typedef of the type to which `t_TYPE` refers, and defines a nested
1167/// `type` typedef of `t_TYPE` otherwise.
1168template <class t_TYPE>
1169struct MovableRefUtil_RemoveReference : bsl::remove_reference<t_TYPE> {
1170};
1171
1172#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1173
1174template <class t_TYPE>
1176 // TYPES
1177 typedef t_TYPE type;
1178};
1179
1180template <class t_TYPE>
1182 // TYPES
1183 typedef t_TYPE type;
1184};
1185
1186template <class t_TYPE>
1188 // TYPES
1189 typedef t_TYPE type;
1190};
1191
1192template <class t_TYPE>
1194 // TYPES
1195 typedef t_TYPE type;
1196};
1197
1198template <class t_TYPE>
1200 // TYPES
1201 typedef t_TYPE type;
1202};
1203
1204template <class t_TYPE>
1206 // TYPES
1207 typedef t_TYPE type;
1208};
1209
1210template <class t_TYPE>
1211struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE> >;
1212 // This partial 'struct' template specialization is not defined.
1213
1214template <class t_TYPE>
1215struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE>&>;
1216 // This partial 'struct' template specialization is not defined.
1217
1218template <class t_TYPE>
1219struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE> >;
1220 // This partial 'struct' template specialization is not defined.
1221
1222template <class t_TYPE>
1223struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE>&>;
1224 // This partial 'struct' template specialization is not defined.
1225
1226#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1227
1228 // ----------------------------------------
1229 // struct MovableRefUtil_AddLvalueReference
1230 // ----------------------------------------
1231
1232#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1233
1234/// This component-private `struct` template provides a metafunction that
1235/// defines a nested `type` typedef that is an lvalue reference to `t_TYPE`.
1236/// If `t_TYPE` is already an `lvalue` reference, then `type` is `t_TYPE`.
1237/// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`. This
1238/// transformation reflects the semantics of _reference collapsing_ in
1239/// section [dec.ref] of the standard.
1240template <class t_TYPE>
1242};
1243
1244#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1245
1246template <>
1248 // TYPES
1249 typedef void type;
1250};
1251
1252template <>
1254 // TYPES
1255 typedef const void type;
1256};
1257
1258template <>
1260 // TYPES
1261 typedef volatile void type;
1262};
1263
1264template <>
1265struct MovableRefUtil_AddLvalueReference<const volatile void> {
1266 // TYPES
1267 typedef const volatile void type;
1268};
1269
1270template <class t_TYPE>
1272 // TYPES
1273 typedef t_TYPE& type;
1274};
1275
1276template <class t_TYPE>
1278 // TYPES
1279 typedef t_TYPE& type;
1280};
1281
1282template <class t_TYPE>
1284 // TYPES
1285 typedef t_TYPE& type;
1286};
1287
1288template <class t_TYPE>
1290 // TYPES
1291 typedef t_TYPE& type;
1292};
1293
1294template <class t_TYPE>
1296 // TYPES
1297 typedef t_TYPE& type;
1298};
1299
1300template <class t_TYPE>
1302 // TYPES
1303 typedef t_TYPE& type;
1304};
1305
1306template <class t_TYPE>
1307struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE> >;
1308 // This partial 'struct' template specialization is not defined.
1309
1310template <class t_TYPE>
1311struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE>&>;
1312 // This partial 'struct' template specialization is not defined.
1313
1314template <class t_TYPE>
1315struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE> >;
1316 // This partial 'struct' template specialization is not defined.
1317
1318template <class t_TYPE>
1319struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE>&>;
1320 // This partial 'struct' template specialization is not defined.
1321
1322#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1323
1324 // -----------------------------------------
1325 // struct MovableRefUtil_AddMovableReference
1326 // -----------------------------------------
1327
1328#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1329
1330/// This component-private `struct` template provides a metafunction that
1331/// defines a nested `type` typedef that, if `t_TYPE` is not a reference
1332/// type, is `MovableRef<t_TYPE>`. Otherwise, if `t_TYPE` is a
1333/// specialization of `MovableRef`, `type` is the same as `t_TYPE`.
1334/// Otherwise, `type` is `t_TYPE&`. This transformation reflects the
1335/// semantics of
1336/// _reference collapsing_ in section [dec.ref] of the standard.
1337template <class t_TYPE>
1338struct MovableRefUtil_AddMovableReference : bsl::add_rvalue_reference<t_TYPE> {
1339};
1340
1341#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1342
1343template <>
1345 // TYPES
1346 typedef void type;
1347};
1348
1349template <>
1351 // TYPES
1352 typedef const void type;
1353};
1354
1355template <>
1357 // TYPES
1358 typedef volatile void type;
1359};
1360
1361template <>
1362struct MovableRefUtil_AddMovableReference<const volatile void> {
1363 // TYPES
1364 typedef const volatile void type;
1365};
1366
1367template <class t_TYPE>
1372
1373template <class t_TYPE>
1375 // TYPES
1376 typedef t_TYPE& type;
1377};
1378
1379template <class t_TYPE>
1384
1385template <class t_TYPE>
1390
1391template <class t_TYPE>
1393 // TYPES
1395};
1396
1397template <class t_TYPE>
1399 // TYPES
1401};
1402
1403template <class t_TYPE>
1404struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE> >;
1405 // This partial 'struct' template specialization is not defined.
1406
1407template <class t_TYPE>
1408struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE>&>;
1409 // This partial 'struct' template specialization is not defined.
1410
1411template <class t_TYPE>
1412struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE> >;
1413 // This partial 'struct' template specialization is not defined.
1414
1415template <class t_TYPE>
1416struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE>&>;
1417 // This partial 'struct' template specialization is not defined.
1418
1419#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1420
1421 // ---------------------------
1422 // struct MovableRefUtil_Decay
1423 // ---------------------------
1424
1425#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1426
1427/// This component-private `struct` template provides a metafunction that
1428/// defines a nested `type` typedef that applies lvalue-to-rvalue,
1429/// array-to-pointer, and function-to-pointer conversions that occur when an
1430/// lvalue of type `t_TYPE` is used as an rvalue, and also removes `const`,
1431/// `volatile`, and reference qualifiers from class types in order to model
1432/// by-value argument passing. For the purpose of this type trait,
1433/// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
1434///
1435/// Formally, let `U` be `MovableRefUtil::RemoveReference<t_TYPE>::type`.
1436/// If `bsl::is_array<U>::value` is true, the member typedef `type` is
1437/// `bsl::remove_extent<U>::type *`. If `bsl::is_function<U>::value` is
1438/// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
1439/// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
1440template <class t_TYPE>
1441struct MovableRefUtil_Decay : bsl::decay<t_TYPE> {
1442};
1443
1444#elif !defined(BSLS_PLATFORM_CMP_IBM) || BSLS_PLATFORM_CMP_VERSION > 4097
1445
1446///Implementation Note
1447///- - - - - - - - - -
1448// The following definition of 'MovableRefUtil_Decay' is for C++03 compilers,
1449// *except* versions of IBM XL C++ prior to 16.0.2.
1450
1451template <class t_TYPE>
1453: bsl::decay<typename MovableRefUtil_RemoveReference<t_TYPE>::type> {
1454};
1455
1456#else
1457
1458///Implementation Note
1459///- - - - - - - - - -
1460// The following implementation of 'MovableRefUtil_Decay' is exclusively for
1461// the IBM XL C++ line of compilers prior to version 16.0.2. This line of
1462// compilers has a defect in which the compiler retains default-argument
1463// information in the type of functions that have default arguments. If the
1464// program attempts to form a typedef to the type of a function with default
1465// arguments, the IBM XL C++ compiler rejects the typedef because it attempts
1466// to form it with default arguments. Since default arguments cannot be
1467// specified anywhere except function declarations, compilation then fails.
1468//
1469// For example, the following code will be rejected:
1470//..
1471// void f(int = 0);
1472//
1473// template <class t_TYPE>
1474// void g(t_TYPE)
1475// {
1476// typedef t_TYPE type; // ERROR: Default arguments cannot be specified
1477// // in a 'typedef'.
1478// }
1479//
1480// void example()
1481// {
1482// g(f); // ERROR: From the 'g' template instantiation here.
1483// }
1484//..
1485// However, typedefs to *pointers* to such function types do not run afoul of
1486// this defect. Fortunately, the specification of 'decay' requires
1487// transforming function types and reference-to-function types to
1488// pointer-to-function types. So, with some careful metaprogramming, the
1489// following implementation avoids triggering this defect.
1490
1491template <class t_TYPE, bool t_IS_FUNCTION = bsl::is_function<t_TYPE>::value>
1492struct MovableRefUtil_DecayImp;
1493
1494template <class t_TYPE>
1495struct MovableRefUtil_DecayImp<t_TYPE, /* t_IS_FUNCTION */ false>
1496: bsl::decay<t_TYPE> {
1497};
1498
1499template <class t_TYPE>
1500struct MovableRefUtil_DecayImp<t_TYPE, /* t_IS_FUNCTION */ true> {
1501 typedef t_TYPE *type;
1502};
1503
1504template <class t_TYPE>
1505struct MovableRefUtil_Decay : MovableRefUtil_DecayImp<t_TYPE> {
1506};
1507
1508template <class t_TYPE>
1509struct MovableRefUtil_Decay<t_TYPE&> : MovableRefUtil_DecayImp<t_TYPE> {
1510};
1511
1512template <class t_TYPE>
1513struct MovableRefUtil_Decay<MovableRef<t_TYPE> >
1514: MovableRefUtil_DecayImp<t_TYPE> {
1515};
1516
1517template <class t_TYPE>
1518struct MovableRefUtil_Decay<MovableRef<t_TYPE>&>
1519: MovableRefUtil_DecayImp<t_TYPE> {
1520};
1521
1522template <class t_TYPE>
1523struct MovableRefUtil_Decay<const MovableRef<t_TYPE> >
1524: MovableRefUtil_DecayImp<t_TYPE> {
1525};
1526
1527template <class t_TYPE>
1528struct MovableRefUtil_Decay<const MovableRef<t_TYPE>&>
1529: MovableRefUtil_DecayImp<t_TYPE> {
1530};
1531
1532template <class t_TYPE>
1533struct MovableRefUtil_Decay<volatile MovableRef<t_TYPE> >;
1534 // This partial 'struct' template specialization is not defined.
1535
1536template <class t_TYPE>
1537struct MovableRefUtil_Decay<volatile MovableRef<t_TYPE>&>;
1538 // This partial 'struct' template specialization is not defined.
1539
1540template <class t_TYPE>
1541struct MovableRefUtil_Decay<const volatile MovableRef<t_TYPE> >;
1542 // This partial 'struct' template specialization is not defined.
1543
1544template <class t_TYPE>
1545struct MovableRefUtil_Decay<const volatile MovableRef<t_TYPE>&>;
1546 // This partial 'struct' template specialization is not defined.
1547
1548#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1549
1550} // close package namespace
1551
1552
1553#endif
1554
1555// ----------------------------------------------------------------------------
1556// Copyright 2015 Bloomberg Finance L.P.
1557//
1558// Licensed under the Apache License, Version 2.0 (the "License");
1559// you may not use this file except in compliance with the License.
1560// You may obtain a copy of the License at
1561//
1562// http://www.apache.org/licenses/LICENSE-2.0
1563//
1564// Unless required by applicable law or agreed to in writing, software
1565// distributed under the License is distributed on an "AS IS" BASIS,
1566// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1567// See the License for the specific language governing permissions and
1568// limitations under the License.
1569// ----------------------------- END-OF-FILE ----------------------------------
1570
1571/** @} */
1572/** @} */
1573/** @} */
Definition bslmf_decay.h:157
Definition bslmf_movableref.h:751
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlbb_blob.h:576
Definition bslmf_addlvaluereference.h:126
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
Definition bslmf_iscopyconstructible.h:242
Definition bslmf_islvaluereference.h:125
Definition bslmf_isnothrowmoveconstructible.h:358
Definition bslmf_isreference.h:137
Definition bslmf_isrvaluereference.h:126
Definition bslmf_movableref.h:835
Definition bslmf_movableref.h:845
Definition bslmf_movableref.h:863
Definition bslmf_movableref.h:801
Definition bslmf_movableref.h:809
Definition bslmf_movableref.h:817
Definition bslmf_movableref.h:825
t_TYPE & type
Definition bslmf_movableref.h:1285
const void type
Definition bslmf_movableref.h:1255
const volatile void type
Definition bslmf_movableref.h:1267
t_TYPE & type
Definition bslmf_movableref.h:1279
void type
Definition bslmf_movableref.h:1249
volatile void type
Definition bslmf_movableref.h:1261
forward declaration
Definition bslmf_movableref.h:1271
t_TYPE & type
Definition bslmf_movableref.h:1273
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1382
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1388
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1394
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1400
const void type
Definition bslmf_movableref.h:1352
const volatile void type
Definition bslmf_movableref.h:1364
t_TYPE & type
Definition bslmf_movableref.h:1376
void type
Definition bslmf_movableref.h:1346
volatile void type
Definition bslmf_movableref.h:1358
forward declaration
Definition bslmf_movableref.h:1368
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1370
forward declaration
Definition bslmf_movableref.h:1453
bsl::true_type IsReference
Definition bslmf_movableref.h:1122
bsl::true_type IsMovableReference
Definition bslmf_movableref.h:1121
bsl::false_type IsLvalueReference
Definition bslmf_movableref.h:1120
bsl::false_type IsMovableReference
Definition bslmf_movableref.h:1110
bsl::true_type IsReference
Definition bslmf_movableref.h:1111
bsl::true_type IsLvalueReference
Definition bslmf_movableref.h:1109
forward declaration
Definition bslmf_movableref.h:1097
bsl::false_type IsLvalueReference
Definition bslmf_movableref.h:1099
bsl::false_type IsReference
Definition bslmf_movableref.h:1101
bsl::false_type IsMovableReference
Definition bslmf_movableref.h:1100
t_TYPE type
Definition bslmf_movableref.h:1183
forward declaration
Definition bslmf_movableref.h:1175
t_TYPE type
Definition bslmf_movableref.h:1177
Definition bslmf_movableref.h:791
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
static bsl::enable_if<!bsl::is_copy_constructible< t_TYPE >::value||bsl::is_nothrow_move_constructible< t_TYPE >::value, MovableRef< t_TYPE > >::type move_if_noexcept(t_TYPE &lvalue) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:936
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1032
static bsl::enable_if<!bsl::is_nothrow_move_constructible< t_TYPE >::value &&bsl::is_copy_constructible< t_TYPE >::value, constt_TYPE & >::type move_if_noexcept(t_TYPE &lvalue) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:915
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:305