BDE 4.39.x 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 will 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 and the argument is known to be movable: when a function
83/// takes a `T&&` as argument with a deduced `T` the deduced type may be an
84/// l-value reference that isn't necessarily movable. When using
85/// `bslmf::MovableRef<T>` with C++11 the type will not be deduced and to turn
86/// an l-value into a movable object it is necessary to explicitly use `move()`
87/// at the call site.
88///
89/// For consistent use across different versions of the C++ standard, a few
90/// utility functions are provided in the utility class `bslmf::MovableRefUtil`.
91/// This class contains functions for moving and accessing objects. To enable
92/// an identical notation to access an object with C++11 (where
93/// `bslmf::MovableRef<T>` is just an l-value of type `T`) and with C++03 where
94/// `bslmf::MovableRef<T>` is a class type referencing an l-value of type `T`,
95/// the function template `bslmf::MovableRefUtil::access(r)` is provided.
96/// Similarly, the function `bslmf::MovableRefUtil::move(r)` provides identical
97/// notation for producing a movable reference in both C++03 and 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 which
102/// defer to the standard library where available). These 7 metafunctions and
103/// 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 is 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 in 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 compiling as 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 of whether it is an actual l-value reference or a
161/// `MovableRef<t_TYPE>`. For a concrete example, 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 of simple move
211/// constructors that use `MovableRef`, and highlight the difference in how
212/// different data members are handled.
213///
214/// First, we create a 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/// /// This `class` provides a view on a C-string.
219/// class StringView {
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 a 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/// /// Create a `StringView` object that refers to the same C-string
240/// /// as the specified `original` object, and reset `original` to not
241/// /// refer to any string.
242/// StringView(bslmf::MovableRef<StringView> original)
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 a non-trivial
254/// `StringView` and a trivial integer field:
255/// @code
256/// /// This class represents an employee card.
257/// class Employee {
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/// /// Create an `Employee` object that has the same value as the
273/// /// specified `original` object, and reset `original` to the default
274/// /// state.
275/// Employee(bslmf::MovableRef<Employee> original)
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 feature is
303/// not available with C++03.
304///
305/// The usage example below demonstrates 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 this class template is rather straightforward, and for
314/// simplicity a few trivial operations are implemented directly in the class
315/// 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/// /// Swap the specified pointers `a` and `b`.
325/// static void swap(t_TYPE*& a, t_TYPE*& b);
326///
327/// public:
328///
329/// /// Create an empty Vector.
330/// Vector();
331///
332/// /// Create a Vector by transferring the content of the specified
333/// /// `other`.
334/// Vector(bslmf::MovableRef<Vector> other); // IMPLICIT
335///
336/// /// Create a Vector by copying the content of the specified `other`.
337/// Vector(const Vector& other);
338///
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/// Vector& operator= (Vector other);
345///
346/// /// Destroy the Vector's elements and release any allocated memory.
347/// ~Vector();
348///
349/// /// Return a reference to the object at the specified `index`.
350/// t_TYPE& operator[](int index) { return this->d_begin[index]; }
351///
352/// /// Return a reference to the object at the specified `index`.
353/// const t_TYPE& operator[](int index) const
354/// { return this->d_begin[index]; }
355///
356/// /// Return a pointer to the first element.
357/// t_TYPE *begin() { return this->d_begin; }
358///
359/// /// Return a pointer to the first element.
360/// const t_TYPE *begin() const { return this->d_begin; }
361///
362/// /// Return the capacity of the Vector.
363/// int capacity() const { return int(this->d_endBuffer - this->d_begin); }
364///
365/// /// Return `true` if the Vector is empty and `false` otherwise.
366/// bool empty() const { return this->d_begin == this->d_end; }
367///
368/// /// Return a pointer to the end of the range.
369/// t_TYPE *end() { return this->d_end; }
370///
371/// /// Return a pointer to the end of the range.
372/// const t_TYPE *end() const { return this->d_end; }
373///
374/// /// Append a copy of the specified `value` to the Vector.
375/// void push_back(const t_TYPE& value);
376///
377/// /// Append an object moving the specified `value` to the new location.
378/// void push_back(bslmf::MovableRef<t_TYPE> value);
379///
380/// /// Reserve enough capacity to fit at least as many elements as
381/// /// specified by `newCapacity`.
382/// void reserve(int newCapacity);
383///
384/// /// Return the size of the object.
385/// int size() const { return int(this->d_end - this->d_begin); }
386///
387/// /// Swap the content of the Vector with the specified `other`.
388/// void swap(Vector& 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 are 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 released 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 straightforward to
472/// implement the copy constructor. First the member pointers are initialized
473/// to null. If `other` is empty there is nothing further to do as it is
474/// desirable to not allocate a buffer for an empty `Vector`. If there are
475/// elements to copy the buffer is set up by calling `reserve()` to create
476/// sufficient capacity. Once that is done elements are copied by iterating
477/// over the elements of `other` and constructing elements using placement new
478/// in the 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 a `MovableRef<Vector<t_TYPE> >` passed as argument
545/// that indicates that the referenced object 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_endBuffer` members
548/// of `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 a
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 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 creating a `Vector<Vector<int> >` and using `push_back()` on this
611/// object 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 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>
661#include <bslmf_isreference.h>
664
665#include <bsls_assert.h>
667#include <bsls_keyword.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 arguments are deducible in all language versions.
682///
683/// \note Note that the
684/// argument list of this macro is variadic in order to support deducing
685/// template arguments, e.g., this macro supports uses like
686/// `BSLMF_MOVABLEREF_DEDUCE(bsl::pair<T1, T2>)` for which the types `T1`
687/// and `T2` are deducible, even though the macro argument contains a comma.
688# define BSLMF_MOVABLEREF_DEDUCE(...) \
689 ::BloombergLP::bslmf::MovableRef_Deduced<__VA_ARGS__>
690#else
691# define BSLMF_MOVABLEREF_DEDUCE(...) \
692 ::BloombergLP::bslmf::MovableRef<__VA_ARGS__>
693#endif
694
695
696namespace bslmf {
697
698struct MovableRefUtil;
699 // forward declaration
700
701/// forward declaration
702template <class t_TYPE>
703struct MovableRefUtil_AddLvalueReference;
704
705/// forward declaration
706template <class t_TYPE>
707struct MovableRefUtil_AddMovableReference;
708
709/// forward declaration
710template <class t_TYPE>
711struct MovableRefUtil_Decay;
712
713/// forward declaration
714template <class t_TYPE>
715struct MovableRefUtil_PropertyTraits;
716
717/// forward declaration
718template <class t_TYPE>
719struct MovableRefUtil_RemoveReference;
720
721#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
722
723/// forward declaration
724template <class t_TYPE>
725struct MovableRef_Helper;
726
727#endif
728
729 // ===============
730 // type MovableRef
731 // ===============
732
733#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
734
735/// The alias template `MovableRef<t_TYPE>` yields an r-value reference of
736/// type `t_TYPE&&`.
737template <class t_TYPE>
738using MovableRef = typename MovableRef_Helper<t_TYPE>::type;
739
740#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
741
742/// The class template `MovableRef<t_TYPE>` provides a reference to a
743/// movable object of type `t_TYPE`. Put differently, a function receiving
744/// an object of this class template can transfer (move) the representation to
745/// a different object and leave the referenced object in an unspecified,
746/// although valid (i.e., it obeys all class invariants), state. With C++11
747/// an r-value reference (`t_TYPE&&`) is used to represent the same
748/// semantics.
749///
750/// See @ref bslmf_movableref
751template <class t_TYPE>
753
754 // DATA
755 t_TYPE *d_pointer;
756
757 // PRIVATE CREATORS
758
759 /// Create an `MovableRef<t_TYPE>` object referencing the object pointed to by the specified `pointer`.
760 ///
761 /// \pre The behavior is undefined if
762 /// `pointer` does not point to an object. This constructor is private
763 /// because a C++11 r-value reference cannot be created like this. For
764 /// information on how to create objects of type `MovableRef<t_TYPE>`
765 /// see `MovableRefUtil::move()`.
766 explicit MovableRef(t_TYPE *pointer);
767
768 // FRIENDS
769 friend struct MovableRefUtil;
770
771 public:
772 // ACCESSORS
773
774 /// Return a reference to the referenced object. In contexts where a
775 /// reference to an object of type `t_TYPE` is needed, a
776 /// `MovableRef<t_TYPE>` behaves like such a reference. For information
777 /// on how to access the reference in contexts where no conversion can
778 /// be used see `MovableRefUtil::access()`.
779 operator t_TYPE&() const;
780};
781
782#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
783
784 // =====================
785 // struct MovableRefUtil
786 // =====================
787
788/// This `struct` provides a collection of utility functions operating on
789/// objects of type `MovableRef<t_TYPE>`. The primary use of these
790/// utilities is to create a consistent notation for using the C++03
791/// `MovableRef<t_TYPE>` objects and the C++11 `t_TYPE&&` r-value
792/// references.
793///
794/// See @ref bslmf_movableref
796
797 public:
798 // TYPES
799
800 /// This `struct` template provides a Boolean metafunction that inherits
801 /// from `bsl::true_type` if the specified `t_TYPE` is an lvalue
802 /// reference, and inherits from `bsl::false_type` otherwise.
803 template <class t_TYPE>
805 : MovableRefUtil_PropertyTraits<t_TYPE>::IsLvalueReference {
806 };
807
808 /// This `struct` template provides a Boolean metafunction that inherits
809 /// from `bsl::true_type` if the specified `t_TYPE` is a specialization
810 /// of `MovableRef`, and inherits from `bsl::false_type` otherwise.
811 template <class t_TYPE>
813 : MovableRefUtil_PropertyTraits<t_TYPE>::IsMovableReference {
814 };
815
816 /// This `struct` template provides a Boolean metafunction that inherits
817 /// from `bsl::true_type` if the specified `t_TYPE` is either an lvalue
818 /// reference or a specialization of `MovableRef`, and inherits from
819 /// `bsl::false_type` otherwise.
820 template <class t_TYPE>
821 struct IsReference : MovableRefUtil_PropertyTraits<t_TYPE>::IsReference {
822 };
823
824 /// This `struct` template provides a metafunction that, if the
825 /// specified `t_TYPE` is a reference type, defines a nested `type`
826 /// typedef of the type to which `t_TYPE` refers, and defines a nested
827 /// `type` typedef of `t_TYPE` otherwise.
828 template <class t_TYPE>
831
832 /// This `struct` template provides a metafunction that defines a nested
833 /// `type` typedef that is an lvalue reference to `t_TYPE`. If `t_TYPE`
834 /// is already an `lvalue` reference, then `type` is `t_TYPE`.
835 /// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`.
836 /// This transformation reflects the semantics of _reference collapsing_
837 /// in section [dec.ref] of the standard.
838 template <class t_TYPE>
841
842 /// This `struct` template provides a metafunction that defines a nested
843 /// `type` typedef that, if `t_TYPE` is not a reference type, is
844 /// `MovableRef<t_TYPE>`. Otherwise, if `t_TYPE` is a specialization of
845 /// `MovableRef`, `type` is the same as `t_TYPE`. Otherwise, `type` is
846 /// `t_TYPE&`. This transformation reflects the semantics of
847 /// _reference collapsing_ in section [dec.ref] of the standard.
848 template <class t_TYPE>
851
852 /// This `struct` template provides a metafunction that defines a nested
853 /// `type` typedef that applies lvalue-to-rvalue, array-to-pointer, and
854 /// function-to-pointer conversions that occur when an lvalue of type
855 /// `t_TYPE` is used as an rvalue, and also removes `const`, `volatile`,
856 /// and reference qualifiers from class types in order to model by-value
857 /// argument passing. For the purpose of this type trait,
858 /// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
859 ///
860 /// Formally, let `U` be
861 /// `MovableRefUtil::RemoveReference<t_TYPE>::type`. If
862 /// `bsl::is_array<U>::value` is true, the member typedef `type` is
863 /// `bsl::remove_extent<U>::type *`. If `bsl::is_function<U>::value` is
864 /// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
865 /// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
866 template <class t_TYPE>
867 struct Decay : MovableRefUtil_Decay<t_TYPE> {
868 };
869
870 // CLASS METHODS
871#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
872 template <class t_TYPE>
874 t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT;
875#else
876 template <class t_TYPE>
877 static t_TYPE& access(t_TYPE& ref) BSLS_KEYWORD_NOEXCEPT;
878 template <class t_TYPE>
880#endif
881 // Return an lvalue reference to the object referenced by the specified
882 // `ref` object. This function is used to provide a uniform interface to
883 // members of an object referenced by `ref`, regardless of whether `ref` is
884 // a `MovableRef` or lvalue reference and whether the compiler supports
885 // C++11 rvalue references. This function is unnecessary (but allowed)
886 // when simply converting `ref` to `t_TYPE&`.
887 //
888 // Please see the component-level documentation for more information on
889 // this function.
890
891#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
892 template <class t_TYPE>
895 move(t_TYPE&& reference) BSLS_KEYWORD_NOEXCEPT;
896#else
897 template <class t_TYPE>
898 static MovableRef<t_TYPE> move(t_TYPE& reference) BSLS_KEYWORD_NOEXCEPT;
899 template <class t_TYPE>
902#endif
903 // Return a movable reference to the object referred to by the specified
904 // `reference`. Note that the C++03 implementation of this function
905 // behaves like a factory for `MovableRef<t_TYPE>` objects. The C++11
906 // implementation of this function behaves exactly like `std::move(value)`
907 // applied to lvalues.
908
909 /// Return a const-qualified reference to the specified `lvalue`. This
910 /// function is selected by overload resolution if the move constructor
911 /// for `t_TYPE` might throw an exception. Constructing a `t_TYPE`
912 /// object from the result will result in the copy constructor being
913 /// invoked rather than the (unsafe) move constructor.
914 template <class t_TYPE>
915 static typename bsl::enable_if<
918 const t_TYPE&>::type
920 {
921 // The implementation is placed here in the class definition to work
922 // around a Microsoft C++ compiler (version 16) bug where the
923 // definition cannot be matched to the declaration when an `enable_if`
924 // is used.
925 return lvalue;
926 }
927
928 /// Return a movable reference to the specified `lvalue`. This function
929 /// is selected by overload resolution if the move constructor for
930 /// `t_TYPE` is nothrow-move-constructible. Constructing a `t_TYPE`
931 /// object from the result will result in the (safe) move constructor being invoked.
932 ///
933 /// \note Note that that the
934 /// `bsl::is_nothrow_move_constructible` trait can be customized in
935 /// C++03 mode to indicate that a type is nothrow-move-constructible.
936 template <class t_TYPE>
937 static typename bsl::enable_if<
940 MovableRef<t_TYPE> >::type
942 {
943 // The implementation is placed here in the class definition to work
944 // around a Microsoft C++ compiler (version 16) bug where the
945 // definition cannot be matched to the declaration when an `enable_if`
946 // is used.
947#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
948 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(
949 lvalue);
950#else
952#endif
953 }
954};
955
956#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
957
958 // ========================
959 // struct MovableRef_Helper
960 // ========================
961
962/// The class template `MovableRef_Helper` just defines a nested type
963/// `type` that is used by an alias template. Using this indirection the
964/// template argument of the alias template is prevented from being deduced.
965///
966/// See @ref bslmf_movableref
967template <class t_TYPE>
968struct MovableRef_Helper {
969
970 public:
971 // TYPES
972
973 /// The type `type` defined to be an r-value reference to the argument
974 /// type of 'MovableRef_Helper.
975 using type = t_TYPE&&;
976};
977
978 // =======================
979 // type MovableRef_Deduced
980 // =======================
981
982/// This component-private alias template names the type `t_TYPE&&` if and
983/// only if the specified `t_TYPE` is not an lvalue reference.
984template <class t_TYPE,
986 int>::type = 0>
987using MovableRef_Deduced = t_TYPE&&;
988
989#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
990
991// ============================================================================
992// INLINE DEFINITIONS
993// ============================================================================
994
995 // ----------------
996 // class MovableRef
997 // ----------------
998
999#ifndef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1000
1001// CREATORS
1002template <class t_TYPE>
1003inline
1004MovableRef<t_TYPE>::MovableRef(t_TYPE *pointer)
1005: d_pointer(pointer)
1006{
1007 BSLS_ASSERT(0 != pointer);
1008}
1009
1010// ACCESSORS
1011template <class t_TYPE>
1012inline
1014{
1015 return *d_pointer;
1016}
1017
1018#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1019
1020 // ---------------------
1021 // struct MovableRefUtil
1022 // ---------------------
1023
1024#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1025
1026// CLASS METHODS
1027template <class t_TYPE>
1028inline
1030 t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT
1031{
1032 return static_cast<typename bsl::remove_reference<t_TYPE>::type&>(ref);
1033}
1034
1035#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1036
1037template <class t_TYPE>
1038inline
1040{
1041 return ref;
1042}
1043
1044template <class t_TYPE>
1045inline
1047{
1048 return ref;
1049}
1050
1051#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1052
1053#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1054
1055template <class t_TYPE>
1056inline
1059{
1060 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(rvalue);
1061}
1062
1063#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1064
1065template <class t_TYPE>
1066inline
1071
1072template <class t_TYPE>
1073inline
1079
1080#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1081
1082 // ------------------------------------
1083 // struct MovableRefUtil_PropertyTraits
1084 // ------------------------------------
1085
1086#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1087
1088/// Component-private class: do not use. Define Boolean-valued
1089/// movable-reference traits for the specified `t_TYPE`.
1090///
1091/// See @ref bslmf_movableref
1092template <class t_TYPE>
1094
1095 // TYPES
1099};
1100
1101#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1102
1103/// Component-private class: do not use. Define Boolean-valued
1104/// movable-reference traits for rvalues of the specified `t_TYPE`.
1105///
1106/// See @ref bslmf_movableref
1107template <class t_TYPE>
1114
1115/// Component-private class: do not use. Define Boolean-valued
1116/// movable-reference traits for lvalues of the specified `t_TYPE`.
1117template <class t_TYPE>
1124
1125/// Component-private class: do not use. Define Boolean-valued
1126/// movable-reference traits for movable references to the specified
1127/// `t_TYPE`.
1128template <class t_TYPE>
1135
1136template <class t_TYPE>
1140
1141template <class t_TYPE>
1143: MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {
1144};
1145
1146template <class t_TYPE>
1150
1151template <class t_TYPE>
1152struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE> >;
1153 // This partial `struct` template specialization is not defined.
1154
1155template <class t_TYPE>
1156struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE>&>;
1157 // This partial `struct` template specialization is not defined.
1158
1159template <class t_TYPE>
1160struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE> >;
1161 // This partial `struct` template specialization is not defined.
1162
1163template <class t_TYPE>
1164struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE>&>;
1165 // This partial `struct` template specialization is not defined.
1166
1167#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1168
1169 // -------------------------------------
1170 // struct MovableRefUtil_RemoveReference
1171 // -------------------------------------
1172
1173#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1174
1175/// This component-private `struct` template provides a metafunction that,
1176/// if the specified `t_TYPE` is a reference type, defines a nested `type`
1177/// typedef of the type to which `t_TYPE` refers, and defines a nested
1178/// `type` typedef of `t_TYPE` otherwise.
1179template <class t_TYPE>
1181};
1182
1183#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1184
1185template <class t_TYPE>
1187 // TYPES
1188 typedef t_TYPE type;
1189};
1190
1191template <class t_TYPE>
1193 // TYPES
1194 typedef t_TYPE type;
1195};
1196
1197template <class t_TYPE>
1199 // TYPES
1200 typedef t_TYPE type;
1201};
1202
1203template <class t_TYPE>
1205 // TYPES
1206 typedef t_TYPE type;
1207};
1208
1209template <class t_TYPE>
1211 // TYPES
1212 typedef t_TYPE type;
1213};
1214
1215template <class t_TYPE>
1217 // TYPES
1218 typedef t_TYPE type;
1219};
1220
1221template <class t_TYPE>
1222struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE> >;
1223 // This partial `struct` template specialization is not defined.
1224
1225template <class t_TYPE>
1226struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE>&>;
1227 // This partial `struct` template specialization is not defined.
1228
1229template <class t_TYPE>
1230struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE> >;
1231 // This partial `struct` template specialization is not defined.
1232
1233template <class t_TYPE>
1234struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE>&>;
1235 // This partial `struct` template specialization is not defined.
1236
1237#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1238
1239 // ----------------------------------------
1240 // struct MovableRefUtil_AddLvalueReference
1241 // ----------------------------------------
1242
1243#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1244
1245/// This component-private `struct` template provides a metafunction that
1246/// defines a nested `type` typedef that is an lvalue reference to `t_TYPE`.
1247/// If `t_TYPE` is already an `lvalue` reference, then `type` is `t_TYPE`.
1248/// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`. This
1249/// transformation reflects the semantics of _reference collapsing_ in
1250/// section [dec.ref] of the standard.
1251template <class t_TYPE>
1253};
1254
1255#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1256
1257template <>
1259 // TYPES
1260 typedef void type;
1261};
1262
1263template <>
1265 // TYPES
1266 typedef const void type;
1267};
1268
1269template <>
1271 // TYPES
1272 typedef volatile void type;
1273};
1274
1275template <>
1276struct MovableRefUtil_AddLvalueReference<const volatile void> {
1277 // TYPES
1278 typedef const volatile void type;
1279};
1280
1281template <class t_TYPE>
1283 // TYPES
1284 typedef t_TYPE& type;
1285};
1286
1287template <class t_TYPE>
1289 // TYPES
1290 typedef t_TYPE& type;
1291};
1292
1293template <class t_TYPE>
1295 // TYPES
1296 typedef t_TYPE& type;
1297};
1298
1299template <class t_TYPE>
1301 // TYPES
1302 typedef t_TYPE& type;
1303};
1304
1305template <class t_TYPE>
1307 // TYPES
1308 typedef t_TYPE& type;
1309};
1310
1311template <class t_TYPE>
1313 // TYPES
1314 typedef t_TYPE& type;
1315};
1316
1317template <class t_TYPE>
1318struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE> >;
1319 // This partial `struct` template specialization is not defined.
1320
1321template <class t_TYPE>
1322struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE>&>;
1323 // This partial `struct` template specialization is not defined.
1324
1325template <class t_TYPE>
1326struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE> >;
1327 // This partial `struct` template specialization is not defined.
1328
1329template <class t_TYPE>
1330struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE>&>;
1331 // This partial `struct` template specialization is not defined.
1332
1333#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1334
1335 // -----------------------------------------
1336 // struct MovableRefUtil_AddMovableReference
1337 // -----------------------------------------
1338
1339#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1340
1341/// This component-private `struct` template provides a metafunction that
1342/// defines a nested `type` typedef that, if `t_TYPE` is not a reference
1343/// type, is `MovableRef<t_TYPE>`. Otherwise, if `t_TYPE` is a
1344/// specialization of `MovableRef`, `type` is the same as `t_TYPE`.
1345/// Otherwise, `type` is `t_TYPE&`. This transformation reflects the
1346/// semantics of
1347/// _reference collapsing_ in section [dec.ref] of the standard.
1348template <class t_TYPE>
1349struct MovableRefUtil_AddMovableReference : bsl::add_rvalue_reference<t_TYPE> {
1350};
1351
1352#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1353
1354template <>
1356 // TYPES
1357 typedef void type;
1358};
1359
1360template <>
1362 // TYPES
1363 typedef const void type;
1364};
1365
1366template <>
1368 // TYPES
1369 typedef volatile void type;
1370};
1371
1372template <>
1373struct MovableRefUtil_AddMovableReference<const volatile void> {
1374 // TYPES
1375 typedef const volatile void type;
1376};
1377
1378template <class t_TYPE>
1383
1384template <class t_TYPE>
1386 // TYPES
1387 typedef t_TYPE& type;
1388};
1389
1390template <class t_TYPE>
1395
1396template <class t_TYPE>
1401
1402template <class t_TYPE>
1404 // TYPES
1406};
1407
1408template <class t_TYPE>
1410 // TYPES
1412};
1413
1414template <class t_TYPE>
1415struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE> >;
1416 // This partial `struct` template specialization is not defined.
1417
1418template <class t_TYPE>
1419struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE>&>;
1420 // This partial `struct` template specialization is not defined.
1421
1422template <class t_TYPE>
1423struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE> >;
1424 // This partial `struct` template specialization is not defined.
1425
1426template <class t_TYPE>
1427struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE>&>;
1428 // This partial `struct` template specialization is not defined.
1429
1430#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1431
1432 // ---------------------------
1433 // struct MovableRefUtil_Decay
1434 // ---------------------------
1435
1436#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
1437
1438/// This component-private `struct` template provides a metafunction that
1439/// defines a nested `type` typedef that applies lvalue-to-rvalue,
1440/// array-to-pointer, and function-to-pointer conversions that occur when an
1441/// lvalue of type `t_TYPE` is used as an rvalue, and also removes `const`,
1442/// `volatile`, and reference qualifiers from class types in order to model
1443/// by-value argument passing. For the purpose of this type trait,
1444/// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
1445///
1446/// Formally, let `U` be `MovableRefUtil::RemoveReference<t_TYPE>::type`.
1447/// If `bsl::is_array<U>::value` is true, the member typedef `type` is
1448/// `bsl::remove_extent<U>::type *`. If `bsl::is_function<U>::value` is
1449/// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
1450/// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
1451template <class t_TYPE>
1452struct MovableRefUtil_Decay : bsl::decay<t_TYPE> {
1453};
1454
1455#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1456
1457///Implementation Note
1458///- - - - - - - - - -
1459// The following definition of `MovableRefUtil_Decay` is for C++03 compilers.
1460
1461template <class t_TYPE>
1463: bsl::decay<typename MovableRefUtil_RemoveReference<t_TYPE>::type> {
1464};
1465
1466#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1467
1468} // close package namespace
1469
1470
1471#endif
1472
1473// ----------------------------------------------------------------------------
1474// Copyright 2015 Bloomberg Finance L.P.
1475//
1476// Licensed under the Apache License, Version 2.0 (the "License");
1477// you may not use this file except in compliance with the License.
1478// You may obtain a copy of the License at
1479//
1480// http://www.apache.org/licenses/LICENSE-2.0
1481//
1482// Unless required by applicable law or agreed to in writing, software
1483// distributed under the License is distributed on an "AS IS" BASIS,
1484// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1485// See the License for the specific language governing permissions and
1486// limitations under the License.
1487// ----------------------------- END-OF-FILE ----------------------------------
1488
1489/** @} */
1490/** @} */
1491/** @} */
Definition bslmf_decay.h:158
Definition bslmf_movableref.h:752
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:624
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
Definition bdlbb_blob.h:579
Definition bslmf_addlvaluereference.h:128
Definition bslmf_enableif.h:530
Definition bslmf_integralconstant.h:261
Definition bslmf_iscopyconstructible.h:242
Definition bslmf_islvaluereference.h:135
Definition bslmf_isnothrowmoveconstructible.h:361
Definition bslmf_isreference.h:137
Definition bslmf_isrvaluereference.h:126
Definition bslmf_removereference.h:153
t_TYPE type
This typedef is an alias to the (template parameter) t_TYPE.
Definition bslmf_removereference.h:156
Definition bslmf_movableref.h:839
Definition bslmf_movableref.h:849
Definition bslmf_movableref.h:867
Definition bslmf_movableref.h:805
Definition bslmf_movableref.h:813
Definition bslmf_movableref.h:821
Definition bslmf_movableref.h:829
t_TYPE & type
Definition bslmf_movableref.h:1296
const void type
Definition bslmf_movableref.h:1266
const volatile void type
Definition bslmf_movableref.h:1278
t_TYPE & type
Definition bslmf_movableref.h:1290
void type
Definition bslmf_movableref.h:1260
volatile void type
Definition bslmf_movableref.h:1272
forward declaration
Definition bslmf_movableref.h:1282
t_TYPE & type
Definition bslmf_movableref.h:1284
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1393
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1399
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1405
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1411
const void type
Definition bslmf_movableref.h:1363
const volatile void type
Definition bslmf_movableref.h:1375
t_TYPE & type
Definition bslmf_movableref.h:1387
void type
Definition bslmf_movableref.h:1357
volatile void type
Definition bslmf_movableref.h:1369
forward declaration
Definition bslmf_movableref.h:1379
bslmf::MovableRef< t_TYPE > type
Definition bslmf_movableref.h:1381
forward declaration
Definition bslmf_movableref.h:1463
bsl::true_type IsReference
Definition bslmf_movableref.h:1133
bsl::true_type IsMovableReference
Definition bslmf_movableref.h:1132
bsl::false_type IsLvalueReference
Definition bslmf_movableref.h:1131
bsl::false_type IsMovableReference
Definition bslmf_movableref.h:1121
bsl::true_type IsReference
Definition bslmf_movableref.h:1122
bsl::true_type IsLvalueReference
Definition bslmf_movableref.h:1120
forward declaration
Definition bslmf_movableref.h:1108
bsl::false_type IsLvalueReference
Definition bslmf_movableref.h:1110
bsl::false_type IsReference
Definition bslmf_movableref.h:1112
bsl::false_type IsMovableReference
Definition bslmf_movableref.h:1111
t_TYPE type
Definition bslmf_movableref.h:1194
forward declaration
Definition bslmf_movableref.h:1186
t_TYPE type
Definition bslmf_movableref.h:1188
Definition bslmf_movableref.h:795
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
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:941
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039
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:919
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:312