// bslmf_movableref.h                                                 -*-C++-*-
#ifndef INCLUDED_BSLMF_MOVABLEREF
#define INCLUDED_BSLMF_MOVABLEREF

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a vocabulary type to enable move semantics.
//
//@CLASSES:
//  bslmf::MovableRef: a template indicating that an object can be moved from
//  bslmf::MovableRefUtil: a namespace for functions dealing with movables
//
//@MACROS:
//  BSLMF_MOVABLEREF_DEDUCE(t_TYPE): movable ref of `t_TYPE` that is deducible
//  BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES: defined if MovableRef<T> is `T&&`
//
//@SEE_ALSO:
//
//@DESCRIPTION: This component provides a class template, `bslmf::MovableRef`
// used to convey the information that an object will not be used anymore so
// that its representation can be transferred elsewhere.  In C++11 terminology
// an object represented by a `bslmf::MovableRef<T>` can be moved from.  This
// component also provides a utility `struct` `bslmf::MovableRefUtil` that
// enables use of identical code for C++03 and C++11 to implement move
// semantics.
//
// An object is /movable/ when it isn't being used in a way depending on its
// current representation after an operation on this object.  For example, when
// passing a temporary object to a function the temporary object is movable: it
// can't be referred to other than in the function call.  When objects are no
// longer be used their internal representation can be transferred to another
// object.  Transferring the internal representation of an object to another
// object is called /moving an object/.  The purpose of `bslmf::MovableRef<T>`
// is to indicate to a function that an object can be moved to another object.
//
// With a C++11 implementation `bslmf::MovableRef<T>` is an alias template for
// `T&&`.  With a C++03 implementation `bslmf::MovableRef<T>` is a class
// template providing l-value access to a movable object.  The objective of
// this component is to provide a name for the concept of a movable object.
// Using a common name enables use of manual move semantics when using C++03.
// With C++11 additionally automatic move semantics is enabled resulting in
// moving objects known to the compiler to go out of scope, e.g., when passing
// a temporary object to a function or returning a local variable.
//
// Using `bslmf::MovableRef<T>` to support movable types enables the
// implementation of move semantics that work with both C++03 and C++11 without
// conditional compilation of the user code.  Only the implementation of the
// component `bslmf_movableref` uses conditional compilation to select the
// appropriate implementation choice.  For a C++11 implementation the use of
// `bslmf::MovableRef<T>` instead of `T&&` has the advantage that the `T` will
// not be deduced an the argument is known to be movable: when a function takes
// a `T&&` as argument with a deduced `T` the deduced type may be an l-value
// reference that isn't necessarily movable.  When using `bslmf::MovableRef<T>`
// with C++11 the type will not be deduced and to turn an l-value into a
// movable object it is necessary to explicitly use `move()` at the call site.
//
// For consistent use across different versions of the C++ standard, a few
// utility functions are provided in the utility class `bslmf::MovableRefUtil`.
// This class contains functions for moving and accessing objects.  To enable
// an identical notation to access an object with C++11 (where
// `bslmf::MovableRef<T>` is just an l-value of type `T`) and with C++03 where
// `bslmf::MovableRef<T>` is a class type referencing an l-value of type `T`,
// the function template `bslmf::MovableRefUtil::access(r)` is provided.
// Similarly, the function `bslmf::MovableRefUtil::move(r)` provides
// identical notation for producing a movable reference in both C++03 and
// C++11.
//
// In addition to the `move` and `access` functions, the
// `bslmf::MovableRefUtil` namespace provides 7 metafunctions that closely
// correspond to similar metafunctions in the C++11 standard library (and
// which defer to the standard library where available).  These 7
// metafunctions and their C++11 equivalents are shown in the table below:
// ```
//   +-----------------------------+------------------------------+
//   | MovableRefUtil trait        | C++11 standard trait         |
//   +-----------------------------+------------------------------+
//   | IsLvalueReference<t_TYPE>   | is_lvalue_reference<t_TYPE>  |
//   | IsMovableReference<t_TYPE>  | is_rvalue_reference<t_TYPE>  |
//   | IsReference<t_TYPE>         | is_reference<t_TYPE>         |
//   | RemoveReference<t_TYPE>     | remove_reference<t_TYPE>     |
//   | AddLvalueReference<t_TYPE>  | add_lvalue_reference<t_TYPE> |
//   | AddMovableReference<t_TYPE> | add_rvalue_reference<t_TYPE> |
//   | Decay<t_TYPE>               | decay<t_TYPE>                |
//   +-----------------------------+------------------------------+
// ```
// Note that volatile-qualified `MovableRef` objects are non-sensical; unlike
// const objects they do not occur "naturally" as a result of argument passing
// or template-argument deduction and there would be no reason for a program
// to create one on purpose.  In C++11, moreover, `volatile MovableRef<T>` is
// an alias for `T&& volatile`, which is not a valid type.  The traits above,
// therefore, will fail to compile when instantiated with a volatile-qualified
// `MovableRef`.  Note that, although `volatile MovableRef<T>` doesn't make
// sense, `MovableRef<volatile T>` is perfectly fine and are equivalent to
// `volatile T&&`.
//
///Use of `MovableRef<t_TYPE>` Parameters
///--------------------------------------
// There are a number of differences how `MovableRef<t_TYPE>` parameters are
// handled between C++03 and C++11 implementations.  Due to the language
// differences there is no way to avoid these.  This component enables use of
// move semantics in both C++03 and C++11 when done right.  It doesn't try to
// make implementation of move semantics easier.  Here are some notes to keep
// in mind when using this component:
//
// 1. When using a `t_TYPE&&` in a context where `t_TYPE` is deduced, the
//    resulting reference does normally *not* refer to an object that can be
//    moved from!  If `bslmf::MovableRef<t_TYPE>` would deduce the type when
//    using a C++11 implementation the name would be rather misleading.  Thus,
//    the `t_TYPE` won't be deduced.  When using a C++03 the type /can/ be
//    deduced.  However, a program depending on the `t_TYPE` being deduced from
//    a `bslmf::MovableRef<t_TYPE>` will not compile with a C++11
//    implementation.
// 2. Returning `MovableRef<t_TYPE>` (or `t_TYPE&&`) from a function is almost
//    always wrong.  In particular note that the same life-time issues apply to
//    `MovableRef<t_TYPE>` as they do to references of objects: when returning
//    a reference the object referred to cannot be on the stack, i.e.,
//    returning a `MovableRef<t_TYPE>` referring to a local variable or a
//    by-value function parameter is certainly wrong.  Returning a
//    `MovableRef<t_TYPE>` to a function parameter received as a reference type
//    can be correct.
// 3. Using the argument of type `MovableRef<t_TYPE>` directly in a function
//    typically results in incorrect behavior either when using C++03 or when
//    using C++11.  Instead, use these arguments together with
//    `MovableRefUtil::move()`, `MovableRefUtil::access()`, or bind them to a
//    non-`const` l-value reference.
//
// The purpose of `access(x)` is to use the same notation for member access to
// `x` independent on whether it is an actual l-value reference or an
// `MovableRef<t_TYPE>`.  For a concrete examples assume `x` is a
// `bsl::pair<A, B>`.  When using a C++11 implementation
// `MovableRef<bsl::pair<A, B> >` is really just a `bsl::pair<A, B>&&` and the
// elements could be accessed using `x.first` and `x.second`.  For a C++03
// implementation `MovableRef<bsl::pair<A, B> >` is a class type and `x.first`
// and `x.second` are not available.  Instead, a reference to the pair needs to
// be obtained that could be done using `static_cast<bsl::pair<A, B >&>(x)` or
// by using a named variable.  To unify the notation between the C++03 and
// C++11 implementation, simultaneously simplifying the C++03 use
// `MovableRefUtil::access(x)` can be used.
//
///Template Deduction and Argument Forwarding
///------------------------------------------
// C++11 has two entirely different uses of the notation `T&&`:
//
// 1. In contexts where the type `T` is not deduced `T&&` indicates an "rvalue
//    reference".  The notation implies that the resources held by the
//    referenced object can be reused, typically because the lifetime of the
//    object is about to end.  An argument of type `T&&` can bind to an rvalue
//    of type `T` or to an lvalue of type `T` that has been explicitly "moved"
//    by the caller.
// 2. In contexts where the type `T` is deduced `T&&` indicates a "forwarding
//    reference".  The argument can be either an rvalue or an lvalue and the
//    called function can preserve the value category (rvalue or lvalue) when
//    forwarding the reference to another function.
//
// The `bslmf::MovableRef<T>` emulation of `T&&` in C++03 works only for rvalue
// references, i.e., the first use of the notation.  The C++11 definition of
// `bslmf::MovableRef<T>` is designed specifically to avoid deduction of `T`,
// thus preventing it from accidentally being used as a forwarding reference
// (which would have the wrong effect in C++03).
//
// For contexts where it is desirable to deduce `T`, the
// `BSLMF_MOVABLEREF_DEDUCE` macro is provided.  When invoked like
// `BSLMF_MOVABLEREF_DEDUCE(T)`, this macro expands to `bslmf::MovableRef<T>`
// in C++03, and a type alias to `T&&` for which substitution fails if `T&&`
// would be an lvalue reference in C++11 and later.  In both cases, the type
// `T` is deducible, and substitution succeeds only if
// `BSLMF_MOVABLEREF_DEDUCE(T)` deduces a movable reference.
//
///Usage
///-----
// This section illustrates intended usage of this component.
//
///Example 1: Difference In Moving Trivial And Non-trivial Fields
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This example will show the definition of a couple simple move constructor
// that use `MovableRef`, and highlight the difference in how different data
// members are handled.
//
// First, we create an minimal type similar to `string_view`.  For simplicity,
// we implement methods we are interested in directly in the class declaration
// and omit the rest:
// ```
// /// This class provides a view on a C-string.
// class StringView {
//
//     // DATA
//     const char *d_string_p;  // pointer to the data
//
//   public:
//     // CREATORS
//     ...
// ```
// Here we define the move constructor for `StringView`.  Note that the
// `original` here is either an object of type 'MovableRef<StringView> (in
// C++03), or an true r-value reference `StringView&&`, in C++11 or later.
// Because the type of `original` may be different when built with different
// language standards, we must take care to manipulate and access the value in
// a way that is syntactically valid irrespective of the language-standard
// being used.  Here, we use `MovableRefUtil::access` to obtain `const &` to
// `original`, and we assign `original` to an l-value reference (`StringView&`)
// to set its value to 0.  These are both operations that support the same
// syntax across language standards:
// ```
//     /// Create a `StringView` object that refers to the same c-string
//     /// as the specified `original` object, and reset `original` to not
//     /// refer to any string.
//     StringView(bslmf::MovableRef<StringView> original)
//     : d_string_p(bslmf::MovableRefUtil::access(original).d_string_p)
//     {
//         StringView& reference = original;
//         reference.d_string_p  = 0;
//     }
//
//     // ACCESSORS
//     ...
// };
// ```
// Now, we define a second class, `Employee`, that contains both non-trivial
// `StringView` and a trivial integer field:
// ```
// /// This class represents an employee card.
// class Employee {
//
//     // DATA
//     StringView d_name;  // employee name
//     int        d_id;    // employee id
//
//   public:
//     // CREATORS
//     ...
// ```
// Here we define the move constructor for `Employee`.  Note that for the data
// members of `original`, `d_id` is a fundamental type and we simply can access
// the value as a `const &`, but `d_name` is a `StringView`, so that we must
// use `MovableRefUtil::move` to move it in a language-standard neutral way:
// ```
//     /// Create an `Employee` object that has the same value as the
//     /// specified `original` object, and reset `original` to the default
//     /// state.
//     Employee(bslmf::MovableRef<Employee> original)
//     : d_name(bslmf::MovableRefUtil::move(
//                            bslmf::MovableRefUtil::access(original).d_name))
//     , d_id(bslmf::MovableRefUtil::access(original).d_id)
//     {
//         Employee& reference = original;
//         reference.d_id = 0;
//     }
//
//     // ACCESSORS
//     ...
// };
// ```
//
///Example 2: Basic `MovableRef<T>` Usage
/// - - - - - - - - - - - - - - - - - - -
// There are two sides of move semantics:
//
// 1. Classes or class templates that are _move-enabled_, i.e., which can
//    transfer their internal representation to another object in some
//    situations.  To become move-enabled a class needs to implement, at
//    least, a move constructor.  It should probably also implement a move
//    assignment operator.
// 2. Users of a potentially move-enabled class may take advantage of moving
//    objects by explicitly indicating that ownership of resources may be
//    transferred.  When using C++11 the compiler can automatically detect
//    some situations where it is safe to move objects but this features is
//    not available with C++03.
//
// The usage example below demonstrate both use cases using a simplified
// version of `std::Vector<T>`.  The class template is simplified to
// concentrate on the aspects relevant to `bslmf::MovableRef<T>`.  Most of the
// operations are just normal implementations to create a container.  The last
// two operations described are using move operations.
//
// Assume we want to implement a class template similar to the standard library
// `vector` facility.  First we declare the class template `Vector<t_TYPE>`.
// The definition of the this class template is rather straight forward, and
// for simplicity a few trivial operations are implemented directly in the
// class definition:
// ```
// template <class t_TYPE>
// class Vector
// {
//     t_TYPE *d_begin;
//     t_TYPE *d_end;
//     t_TYPE *d_endBuffer;
//
//     static void swap(t_TYPE*& a, t_TYPE*& b);
//         // Swap the specified pointers 'a' and 'b'.
//
//   public:
//
//     /// Create an empty Vector.
//     Vector();
//
//     /// Create a Vector by transferring the content of the specified
//     /// `other`.
//     Vector(bslmf::MovableRef<Vector> other);                    // IMPLICIT
//
//     /// Create a Vector by copying the content of the specified `other`.
//     Vector(const Vector& other);
//
//     /// Assign a Vector by copying the content of the specified `other`
//     /// and return a reference to this object.  Note that `other` is
//     /// passed by value to have the copy or move already be done, or
//     /// even elided.  Within the body of the assignment operator the
//     /// content of `this` and `other` are simply swapped.
//     Vector& operator= (Vector other);
//
//     /// Destroy the Vector's elements and release any allocated memory.
//     ~Vector();
//
//     /// Return a reference to the object at the specified `index`.
//     t_TYPE&       operator[](int index)    { return this->d_begin[index]; }
//
//     /// Return a reference to the object at the specified `index`.
//     const t_TYPE& operator[](int index) const
//                                            { return this->d_begin[index]; }
//
//     /// Return a pointer to the first element.
//     t_TYPE     *begin()       { return this->d_begin; }
//
//     /// Return a pointer to the first element.
//     const t_TYPE *begin() const { return this->d_begin; }
//
//     /// Return the capacity of the Vector.
//     int capacity() const { return int(this->d_endBuffer - this->d_begin); }
//
//     /// Return `true` if the Vector is empty and `false` otherwise.
//     bool empty() const { return this->d_begin == this->d_end; }
//
//     /// Return a pointer to the end of the range.
//     t_TYPE     *end()       { return this->d_end; }
//
//     /// Return a pointer to the end of the range.
//     const t_TYPE *end() const { return this->d_end; }
//
//     /// Append a copy of the specified `value` to the Vector.
//     void push_back(const t_TYPE& value);
//
//     /// Append an object moving the specified `value` to the new location.
//     void push_back(bslmf::MovableRef<t_TYPE> value);
//
//     /// Reserve enough capacity to fit at least as many elements as
//     /// specified by `newCapacity`.
//     void reserve(int newCapacity);
//
//     /// Return the size of the object.
//     int size() const { return int(this->d_end - this->d_begin); }
//
//     /// Swap the content of the Vector with the specified `other`.
//     void swap(Vector& other);
// };
// ```
// The class stores pointers to the begin and the end of the elements as well
// as a pointer to the end of the allocated buffer.  If there are no elements,
// null pointers are stored.  There a number of accessors similar to the
// accessors used by `std::Vector<t_TYPE>`.
//
// The default constructor creates an empty `Vector<t_TYPE>` by simply
// initializing all member pointers to be null pointers:
// ```
// template <class t_TYPE>
// Vector<t_TYPE>::Vector()
//     : d_begin()
//     , d_end()
//     , d_endBuffer()
// {
// }
// ```
// To leverage already implemented functionality some of the member functions
// operate on a temporary `Vector<t_TYPE>` and move the result into place using
// the `swap()` member function that simply does a memberwise `swap()` (the
// function swapping pointers is implemented here to avoid any dependency on
// functions defined in another level):
// ```
// template <class t_TYPE>
// void Vector<t_TYPE>::swap(t_TYPE*& a, t_TYPE*& b)
// {
//     t_TYPE *tmp = a;
//     a = b;
//     b = tmp;
// }
// template <class t_TYPE>
// void Vector<t_TYPE>::swap(Vector& other)
// {
//     this->swap(this->d_begin, other.d_begin);
//     this->swap(this->d_end, other.d_end);
//     this->swap(this->d_endBuffer, other.d_endBuffer);
// }
// ```
// The member function `reserve()` arranges for the `Vector<t_TYPE>` to have
// enough capacity for the number of elements specified as argument.  The
// function first creates an empty `Vector<t_TYPE>` called `tmp` and sets `tmp`
// up to have enough capacity by allocating sufficient memory and assigning the
// different members to point to the allocated buffer.  The function then
// iterates over the elements of `this` and for each element it constructs a
// new element in `tmp`.
// ```
// template <class t_TYPE>
// void Vector<t_TYPE>::reserve(int newCapacity)
// {
//     if (this->capacity() < newCapacity) {
//         Vector tmp;
//         int    size = int(sizeof(t_TYPE) * newCapacity);
//         tmp.d_begin = static_cast<t_TYPE*>(operator new(size));
//         tmp.d_end = tmp.d_begin;
//         tmp.d_endBuffer = tmp.d_begin + newCapacity;
//
//         for (t_TYPE* it = this->d_begin; it != this->d_end; ++it) {
//             new (tmp.d_end) t_TYPE(*it);
//             ++tmp.d_end;
//         }
//         this->swap(tmp);
//     }
// }
// ```
// Any allocated data and constructed elements need to be release in the
// destructor.  The destructor does so by calling the destructor of the
// elements in the buffer from back to front.  Once the elements are destroyed
// the buffer is released:
// ```
// template <class t_TYPE>
// Vector<t_TYPE>::~Vector()
// {
//     if (this->d_begin) {
//         while (this->d_begin != this->d_end) {
//             --this->d_end;
//             this->d_end->~t_TYPE();
//         }
//         operator delete(this->d_begin);
//     }
// }
// ```
// Using `reserve()` and constructing the elements it is straight forward to
// implement the copy constructor.  First the member pointers are initialed to
// null.  If `other` is empty there is nothing further to do as it is desirable
// to not allocate a buffer for an empty `Vector`.  If there are elements to
// copy the buffer is set up by calling `reserve()` to create sufficient
// capacity.  Once that is done elements are copied by iterating over the
// elements of `other` and constructing elements using placement new in the
// appropriate location.
// ```
// template <class t_TYPE>
// Vector<t_TYPE>::Vector(const Vector& other)
//     : d_begin()
//     , d_end()
//     , d_endBuffer()
// {
//     if (!other.empty()) {
//         this->reserve(4 < other.size()? other.size(): 4);
//
//         assert(other.size() <= this->capacity());
//         for (t_TYPE* it = other.d_begin; it != other.d_end; ++it) {
//             new (this->d_end) t_TYPE(*it);
//             ++this->d_end;
//         }
//     }
// }
// ```
// A simple copy assignment operator can be implemented in terms of copy/move
// constructors, `swap()`, and destructor (in a real implementation the copy
// assignment would probably try to use already allocated objects).  In this
// implementation that argument is taken by value, i.e., the argument is
// already constructed using copy or move construction (which may have been
// elided), the content of `this` is swapped with the content of `other`
// leaving this in the desired state, and the destructor will release the
// former representation of `this` when `other` is destroyed':
// ```
// template <class t_TYPE>
// Vector<t_TYPE>& Vector<t_TYPE>::operator= (Vector other)
// {
//     this->swap(other);
//     return *this;
// }
// ```
// To complete the normal C++03 operations of `Vector<t_TYPE>` the only
// remaining member function is `push_back()`.  This function calls `reserve()`
// to obtain more capacity if the current capacity is filled and then
// constructs the new element at the location pointed to by `d_end`:
// ```
// template <class t_TYPE>
// void Vector<t_TYPE>::push_back(const t_TYPE& value)
// {
//     if (this->d_end == this->d_endBuffer) {
//         this->reserve(this->size()? 2 * this->size() : 4);
//     }
//     assert(this->d_end != this->d_endBuffer);
//     new(this->d_end) t_TYPE(value);
//     ++this->d_end;
// }
// ```
// The first operation actually demonstrating the use of `MovableRef<t_TYPE>`
// is the move constructor:
// ```
// template <class t_TYPE>
// Vector<t_TYPE>::Vector(bslmf::MovableRef<Vector> other)
//     : d_begin(bslmf::MovableRefUtil::access(other).d_begin)
//     , d_end(bslmf::MovableRefUtil::access(other).d_end)
//     , d_endBuffer(bslmf::MovableRefUtil::access(other).d_endBuffer)
// {
//     Vector& reference(other);
//     reference.d_begin = 0;
//     reference.d_end = 0;
//     reference.d_endBuffer = 0;
// }
// ```
// This constructor gets an `MovableRef<Vector<t_TYPE> >` passed as argument
// that indicates that the referenced objects can be modified as long as it is
// left in a state meeting the class invariants.  The implementation of this
// constructor first copies the `d_begin`, `d_end`, and `d_capacity` members of
// `other`.  Since `other` is either an object of type
// `MovableRef<Vector<t_TYPE> >` (when compiling using a C++03 compiler) or an
// r-value reference `Vector<t_TYPE>&&` the members are accessed using
// `MovableRefUtil::access(other)` to get a reference to a `Vector<t_TYPE>`.
// Within the body of the constructor an l-value reference is obtained either
// via the conversion operator of `MovableRef<T>` or directly as `other` is
// just an l-value when compiling with a C++11 compiler.  This reference is
// used to set the pointer members of the object referenced by `other` to `0`
// completing the move of the content to the object under construction.
//
// Finally, a move version of `push_back()` is provided: it takes an
// `MovableRef<t_TYPE>` as argument.  The type of this argument indicates that
// the state can be transferred and after arranging enough capacity in the
// `Vector<t_TYPE>` object a new element is move constructed at the position
// `d_end`:
// ```
// template <class t_TYPE>
// void Vector<t_TYPE>::push_back(bslmf::MovableRef<t_TYPE> value)
// {
//     if (this->d_end == this->d_endBuffer) {
//         this->reserve(this->size()? int(1.5 * this->size()): 4);
//     }
//     assert(this->d_end != this->d_endBuffer);
//     new(this->d_end) t_TYPE(bslmf::MovableRefUtil::move(value));
//     ++this->d_end;
// }
// ```
// Note that this implementation of `push_back()` uses
// `bslmf::MovableRefUtil::move(value)` to move the argument.  For a C++03
// implementation the argument would be moved even when using `value` directly
// because the type of `value` stays `bslmf::MovableRef<t_TYPE>`.  However, for
// a C++11 implementation the argument `value` is an l-value and using it
// directly would result in a copy.
//
// To demonstrate the newly created `Vector<t_TYPE>` class in action, first a
// `Vector<int>` is created and filled with a few elements:
// ```
// Vector<int> vector0;
// for (int i = 0; i != 5; ++i) {
//     vector0.push_back(i);
// }
// for (int i = 0; i != 5; ++i) {
//     assert(vector0[i] == i);
// }
// ```
// To verify that copying of `Vector<t_TYPE>` objects works, a copy is created:
// ```
// Vector<int> vector1(vector0);
// assert(vector1.size() == 5);
// assert(vector1.size() == vector0.size());
// for (int i = 0; i != vector1.size(); ++i) {
//     assert(vector1[i] == i);
//     assert(vector1[i] == vector0[i]);
// }
// ```
// When using moving this `vector0` to a new location the representation of the
// new object should use the original `begin()`:
// ```
// const int   *first = vector0.begin();
// Vector<int>  vector2(bslmf::MovableRefUtil::move(vector0));
// assert(first == vector2.begin());
// ```
// When create a `Vector<Vector<int> >` and using `push_back()` on this object
// with `vector2` a copy should be inserted:
// ```
// Vector<Vector<int> > vVector;
// vVector.push_back(vector2);                          // copy
// assert(vector2.size() == 5);
// assert(vVector.size() == 1);
// assert(vVector[0].size() == vector2.size());
// assert(vVector[0].begin() != first);
// for (int i = 0; i != 5; ++i) {
//     assert(vVector[0][i] == i);
//     assert(vector2[i] == i);
// }
// ```
// When adding another element by moving `vector2` the `begin()` of the newly
// inserted element will be the same as `first`, i.e., the representation is
// transferred:
// ```
// vVector.push_back(bslmf::MovableRefUtil::move(vector2)); // move
// assert(vVector.size() == 2);
// assert(vVector[1].begin() == first);
// assert(vVector[1].size() == 5);
// ```
// Compiling this code with both C++03 and C++11 compilers shows that there is
// no need for conditional compilation in when using `MovableRef<t_TYPE>` while
// move semantics is enabled in both modes.
// ----------------------------------------------------------------------------

#include <bslscm_version.h>

#include <bslmf_addlvaluereference.h>
#include <bslmf_addrvaluereference.h>
#include <bslmf_decay.h>
#include <bslmf_enableif.h>
#include <bslmf_iscopyconstructible.h>
#include <bslmf_islvaluereference.h>
#include <bslmf_isnothrowmoveconstructible.h>
#include <bslmf_isreference.h>
#include <bslmf_isrvaluereference.h>
#include <bslmf_removereference.h>

#include <bsls_assert.h>
#include <bsls_compilerfeatures.h>
#include <bsls_keyword.h>
#include <bsls_platform.h>
#include <bsls_util.h>

#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) &&               \
    defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES)
#define BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
// This macro indicates whether the component uses C++11 r-value references to
// implement 'bslmf::MovableRef<t_TYPE>'.  It will evaluate to 'false' for
// C++03 implementations and to 'true' for proper C++11 implementations.  For
// partial C++11 implementations it may evaluate to 'false' because both
// r-value reference and alias templates need to be supported.
#endif

#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
/// This macro expands to a movable reference to `__VA_ARGS__` for which the
/// arguments are deducible in all language versions.  Note that the
/// argument list of this macro is variadic in order to support deducing
/// template arguments, e.g., this macro supports uses like
/// `BSLMF_MOVABLEREF_DEDUCE(bsl::pair<T1, T2>)` for which the  types `T1`
/// and `T2` are deducible, even though the macro argument contains a comma.
#   define BSLMF_MOVABLEREF_DEDUCE(...)                                       \
        ::BloombergLP::bslmf::MovableRef_Deduced<__VA_ARGS__>
#else
#    define BSLMF_MOVABLEREF_DEDUCE(...)                                      \
        ::BloombergLP::bslmf::MovableRef<__VA_ARGS__>
#endif

namespace BloombergLP {
namespace bslmf {

struct MovableRefUtil;
    // forward declaration

/// forward declaration
template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference;

/// forward declaration
template <class t_TYPE>
struct MovableRefUtil_AddMovableReference;

/// forward declaration
template <class t_TYPE>
struct MovableRefUtil_Decay;

/// forward declaration
template <class t_TYPE>
struct MovableRefUtil_PropertyTraits;

/// forward declaration
template <class t_TYPE>
struct MovableRefUtil_RemoveReference;

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// forward declaration
template <class t_TYPE>
struct MovableRef_Helper;

#endif

                               // ===============
                               // type MovableRef
                               // ===============

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// The alias template `MovableRef<t_TYPE>` yields an r-value reference of
/// type `t_TYPE&&`.
template <class t_TYPE>
using MovableRef = typename MovableRef_Helper<t_TYPE>::type;

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

/// The class template `MovableRef<t_TYPE>` provides a reference to a
/// movable object of type `t_TYPE`.  Put differently, a function receiving
/// an object this class template can transfer (move) the representation to
/// a different object and leave the referenced object in an unspecified,
/// although valid (i.e., it obeys all class invariants), state.  With C++11
/// an r-value reference (`t_TYPE&&`) is used to represent the same
/// semantics.
template <class t_TYPE>
class MovableRef {

    // DATA
    t_TYPE *d_pointer;

    // PRIVATE CREATORS

    /// Create an `MovableRef<t_TYPE>` object referencing the object pointed
    /// to by the specified `pointer`.  The behavior is undefined if
    /// `pointer` does not point to an object.  This constructor is private
    /// because a C++11 r-value reference cannot be created like this.  For
    /// information on how to create objects of type `MovableRef<t_TYPE>`
    /// see `MovableRefUtil::move()`.
    explicit MovableRef(t_TYPE *pointer);

    // FRIENDS
    friend struct MovableRefUtil;

  public:
    // ACCESSORS

    /// Return a reference to the referenced object.  In contexts where a
    /// reference to an object of type `t_TYPE` is needed, a
    /// `MovableRef<t_TYPE>` behaves like such a reference.  For information
    /// on how to access the reference in contexts where no conversion can
    /// be used see `MovableRefUtil::access()`.
    operator t_TYPE&() const;
};

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                            // =====================
                            // struct MovableRefUtil
                            // =====================

/// This `struct` provides a collection of utility functions operating on
/// objects of type `MovableRef<t_TYPE>`.  The primary use of these
/// utilities to create a consistent notation for using the C++03
/// `MovableRef<t_TYPE>` objects and the C++11 `t_TYPE&&` r-value
/// references.
struct MovableRefUtil {

  public:
    // TYPES

    /// This `struct` template provides a Boolean metafunction that inherits
    /// from `bsl::true_type` if the specified `t_TYPE` is an lvalue
    /// reference, and inherits from `bsl::false_type` otherwise.
    template <class t_TYPE>
    struct IsLvalueReference
    : MovableRefUtil_PropertyTraits<t_TYPE>::IsLvalueReference {
    };

    /// This `struct` template provides a Boolean metafunction that inherits
    /// from `bsl::true_type` if the specified `t_TYPE` is a specialization
    /// of `MovableRef`, and inherits from `bsl::false_type` otherwise.
    template <class t_TYPE>
    struct IsMovableReference
    : MovableRefUtil_PropertyTraits<t_TYPE>::IsMovableReference {
    };

    /// This `struct` template provides a Boolean metafunction that inherits
    /// from `bsl::true_type` if the specified `t_TYPE` is either an lvalue
    /// reference or a specialization of `MovableRef`, and inherits from
    /// `bsl::false_type` otherwise.
    template <class t_TYPE>
    struct IsReference : MovableRefUtil_PropertyTraits<t_TYPE>::IsReference {
    };

    /// This `struct` template provides a metafunction that, if the
    /// specified `t_TYPE` is a reference type, defines a nested `type`
    /// typedef of the type to which `t_TYPE` refers, and defines a nested
    /// `type` typedef of `t_TYPE` otherwise.
    template <class t_TYPE>
    struct RemoveReference : MovableRefUtil_RemoveReference<t_TYPE> {
    };

    /// This `struct` template provides a metafunction that defines a nested
    /// `type` typedef that is an lvalue reference to `t_TYPE`.  If `t_TYPE`
    /// is already an `lvalue` reference, then `type` is `t_TYPE`.
    /// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`.
    /// This transformation reflects the semantics of _reference collapsing_
    /// in section [dec.ref] of the standard.
    template <class t_TYPE>
    struct AddLvalueReference : MovableRefUtil_AddLvalueReference<t_TYPE> {
    };

    /// This `struct` template provides a metafunction that defines a nested
    /// `type` typedef that, if `t_TYPE` is not a reference type, is
    /// `MovableRef<t_TYPE>`.  Otherwise, if `t_TYPE` is a specialization of
    /// `MovableRef`, `type` is the same as `t_TYPE`.  Otherwise, `type` is
    /// `t_TYPE&`.  This transformation reflects the semantics of
    /// _reference collapsing_ in section [dec.ref] of the standard.
    template <class t_TYPE>
    struct AddMovableReference : MovableRefUtil_AddMovableReference<t_TYPE> {
    };

    /// This `struct` template provides a metafunction that defines a nested
    /// `type` typedef that applies lvalue-to-rvalue, array-to-pointer, and
    /// function-to-pointer conversions that occur when an lvalue of type
    /// `t_TYPE` is used as an rvalue, and also removes `const`, `volatile`,
    /// and reference qualifiers from class types in order to model by-value
    /// argument passing.  For the purpose of this type trait,
    /// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
    ///
    /// Formally, let `U` be
    /// `MovableRefUtil::RemoveReference<t_TYPE>::type`.  If
    /// `bsl::is_array<U>::value` is true, the member typedef `type` is
    /// `bsl::remove_extent<U>::type *`.  If `bsl::is_function<U>::value` is
    /// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
    /// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
    template <class t_TYPE>
    struct Decay : MovableRefUtil_Decay<t_TYPE> {
    };

    // CLASS METHODS
#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
    template <class t_TYPE>
    static typename bsl::remove_reference<t_TYPE>::type& access(
                                           t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT;
#else
    template <class t_TYPE>
    static t_TYPE& access(t_TYPE& ref) BSLS_KEYWORD_NOEXCEPT;
    template <class t_TYPE>
    static t_TYPE& access(MovableRef<t_TYPE> ref) BSLS_KEYWORD_NOEXCEPT;
#endif
    // Return an lvalue reference to the object referenced by the specified
    // 'ref' object.  This function is used to provide a uniform interface to
    // members of an object reference by 'ref', regardless of whether 'ref' is
    // an 'MovableRef' or lvalue reference and whether the compiler supports
    // C++11 rvalue references.  This function is unnecessary (but allowed)
    // when simply converting 'ref' to 't_TYPE&'.
    //
    // Please see the component-level documentation for more information on
    // this function.

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
    template <class t_TYPE>
    static BSLS_KEYWORD_CONSTEXPR
        MovableRef<typename bsl::remove_reference<t_TYPE>::type>
        move(t_TYPE&& reference) BSLS_KEYWORD_NOEXCEPT;
#else
    template <class t_TYPE>
    static MovableRef<t_TYPE> move(t_TYPE& reference) BSLS_KEYWORD_NOEXCEPT;
    template <class t_TYPE>
    static MovableRef<typename bsl::remove_reference<t_TYPE>::type> move(
                           MovableRef<t_TYPE> reference) BSLS_KEYWORD_NOEXCEPT;
#endif
    // Return a movable reference to the object referred to by the specified
    // 'reference'.  Note that the C++03 implementation of this function
    // behaves like a factory for 'MovableRef<t_TYPE>' objects.  The C++11
    // implementation of this function behaves exactly like 'std::move(value)'
    // applied to lvalues.

    /// Return a const-qualified reference to the specified `lvalue`.  This
    /// function is selected by overload resolution if the move constructor
    /// for `t_TYPE` might throw an exception.  Constructing a `t_TYPE`
    /// object from the result will result in the copy constructor being
    /// invoked rather than the (unsafe) move constructor.
    template <class t_TYPE>
    static typename bsl::enable_if<
        !bsl::is_nothrow_move_constructible<t_TYPE>::value &&
            bsl::is_copy_constructible<t_TYPE>::value,
        const t_TYPE&>::type
    move_if_noexcept(t_TYPE& lvalue) BSLS_KEYWORD_NOEXCEPT
    {
        // The implementation is placed here in the class definition to work
        // around a Microsoft C++ compiler (version 16) bug where the
        // definition cannot be matched to the declaration when an 'enable_if'
        // is used.
        return lvalue;
    }

    /// Return a movable reference to the specified `lvalue`.  This function
    /// is selected by overload resolution if the move constructor for
    /// `t_TYPE` is nothrow-move-constructible.  Constructing a `t_TYPE`
    /// object from the result will result in the (safe) move constructor
    /// being invoked.  Note that that the
    /// `bsl::is_nothrow_move_constructible` trait can be customized in
    /// C++03 mode to indicate that a type is nothrow-move-constructible.
    template <class t_TYPE>
    static typename 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
    {
        // The implementation is placed here in the class definition to work
        // around a Microsoft C++ compiler (version 16) bug where the
        // definition cannot be matched to the declaration when an 'enable_if'
        // is used.
#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
        return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(
                                                                       lvalue);
#else
        return MovableRef<t_TYPE>(bsls::Util::addressOf(lvalue));
#endif
    }
};

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

                          // ========================
                          // struct MovableRef_Helper
                          // ========================

/// The class template `MovableRef_Helper` just defines a nested type
/// `type` that is used by an alias template.  Using this indirection the
/// template argument of the alias template is prevented from being deduced.
template <class t_TYPE>
struct MovableRef_Helper {

  public:
    // TYPES

    /// The type `type` defined to be an r-value reference to the argument
    /// type of 'MovableRef_Helper.
    using type = t_TYPE&&;
};

                          // =======================
                          // type MovableRef_Deduced
                          // =======================

/// This component-private alias template names the type `t_TYPE&&` if and
/// only if the specified `t_TYPE` is not an lvalue reference.
template <class t_TYPE,
          typename bsl::enable_if<!bsl::is_lvalue_reference<t_TYPE>::value,
                                  int>::type = 0>
using MovableRef_Deduced = t_TYPE&&;

#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

// ============================================================================
//                             INLINE DEFINITIONS
// ============================================================================

                              // ----------------
                              // class MovableRef
                              // ----------------

#ifndef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

// CREATORS
template <class t_TYPE>
inline
MovableRef<t_TYPE>::MovableRef(t_TYPE *pointer)
: d_pointer(pointer)
{
    BSLS_ASSERT(0 != pointer);
}

// ACCESSORS
template <class t_TYPE>
inline
MovableRef<t_TYPE>::operator t_TYPE&() const
{
    return *d_pointer;
}

#endif // defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                           // ---------------------
                           // struct MovableRefUtil
                           // ---------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

// CLASS METHODS
template <class t_TYPE>
inline
typename bsl::remove_reference<t_TYPE>::type& MovableRefUtil::access(
                                            t_TYPE&& ref) BSLS_KEYWORD_NOEXCEPT
{
    return static_cast<typename bsl::remove_reference<t_TYPE>::type&>(ref);
}

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

template <class t_TYPE>
inline
t_TYPE& MovableRefUtil::access(t_TYPE& ref) BSLS_KEYWORD_NOEXCEPT
{
    return ref;
}

template <class t_TYPE>
inline
t_TYPE& MovableRefUtil::access(MovableRef<t_TYPE> ref) BSLS_KEYWORD_NOEXCEPT
{
    return ref;
}

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

template <class t_TYPE>
inline
BSLS_KEYWORD_CONSTEXPR MovableRef<typename bsl::remove_reference<t_TYPE>::type>
MovableRefUtil::move(t_TYPE&& rvalue) BSLS_KEYWORD_NOEXCEPT
{
    return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(rvalue);
}

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

template <class t_TYPE>
inline
MovableRef<t_TYPE> MovableRefUtil::move(t_TYPE& lvalue) BSLS_KEYWORD_NOEXCEPT
{
    return MovableRef<t_TYPE>(bsls::Util::addressOf(lvalue));
}

template <class t_TYPE>
inline
MovableRef<typename bsl::remove_reference<t_TYPE>::type> MovableRefUtil::move(
                               MovableRef<t_TYPE> rvalue) BSLS_KEYWORD_NOEXCEPT
{
    return rvalue;
}

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                    // ------------------------------------
                    // struct MovableRefUtil_PropertyTraits
                    // ------------------------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// Component-private class: do not use.  Define Boolean-valued
/// movable-reference traits for the specified `t_TYPE`.
template <class t_TYPE>
struct MovableRefUtil_PropertyTraits {

    // TYPES
    typedef bsl::is_lvalue_reference<t_TYPE> IsLvalueReference;
    typedef bsl::is_rvalue_reference<t_TYPE> IsMovableReference;
    typedef bsl::is_reference<t_TYPE>        IsReference;
};

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

/// Component-private class: do not use.  Define Boolean-valued
/// movable-reference traits for rvalues of the specified `t_TYPE`.
template <class t_TYPE>
struct MovableRefUtil_PropertyTraits {

    typedef bsl::false_type IsLvalueReference;
    typedef bsl::false_type IsMovableReference;
    typedef bsl::false_type IsReference;
};

/// Component-private class: do not use.  Define Boolean-valued
/// movable-reference traits for lvalues of the specified `t_TYPE`.
template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<t_TYPE&> {

    typedef bsl::true_type  IsLvalueReference;
    typedef bsl::false_type IsMovableReference;
    typedef bsl::true_type  IsReference;
};

/// Component-private class: do not use.  Define Boolean-valued
/// movable-reference traits for movable references to the specified
/// `t_TYPE`.
template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {

    typedef bsl::false_type IsLvalueReference;
    typedef bsl::true_type  IsMovableReference;
    typedef bsl::true_type  IsReference;
};

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<MovableRef<t_TYPE>&>
: MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {
};

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<const MovableRef<t_TYPE> >
: MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {
};

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<const MovableRef<t_TYPE>&>
: MovableRefUtil_PropertyTraits<MovableRef<t_TYPE> > {
};

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_PropertyTraits<const volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                    // -------------------------------------
                    // struct MovableRefUtil_RemoveReference
                    // -------------------------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// This component-private `struct` template provides a metafunction that,
/// if the specified `t_TYPE` is a reference type, defines a nested `type`
/// typedef of the type to which `t_TYPE` refers, and defines a nested
/// `type` typedef of `t_TYPE` otherwise.
template <class t_TYPE>
struct MovableRefUtil_RemoveReference : bsl::remove_reference<t_TYPE> {
};

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

template <class t_TYPE>
struct MovableRefUtil_RemoveReference {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<t_TYPE&> {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<bslmf::MovableRef<t_TYPE> > {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<bslmf::MovableRef<t_TYPE>&> {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<const bslmf::MovableRef<t_TYPE> > {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<const bslmf::MovableRef<t_TYPE>&> {
    // TYPES
    typedef t_TYPE type;
};

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_RemoveReference<const volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                  // ----------------------------------------
                  // struct MovableRefUtil_AddLvalueReference
                  // ----------------------------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// This component-private `struct` template provides a metafunction that
/// defines a nested `type` typedef that is an lvalue reference to `t_TYPE`.
/// If `t_TYPE` is already an `lvalue` reference, then `type` is `t_TYPE`.
/// Otherwise, if `t_TYPE` is `MovableRef<T2>`, then `type` is `T2&`.  This
/// transformation reflects the semantics of _reference collapsing_ in
/// section [dec.ref] of the standard.
template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference : bsl::add_lvalue_reference<t_TYPE> {
};

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

template <>
struct MovableRefUtil_AddLvalueReference<void> {
    // TYPES
    typedef void type;
};

template <>
struct MovableRefUtil_AddLvalueReference<const void> {
    // TYPES
    typedef const void type;
};

template <>
struct MovableRefUtil_AddLvalueReference<volatile void> {
    // TYPES
    typedef volatile void type;
};

template <>
struct MovableRefUtil_AddLvalueReference<const volatile void> {
    // TYPES
    typedef const volatile void type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<t_TYPE&> {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<MovableRef<t_TYPE> > {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<MovableRef<t_TYPE>&> {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<const MovableRef<t_TYPE> > {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<const MovableRef<t_TYPE>&> {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddLvalueReference<const volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                  // -----------------------------------------
                  // struct MovableRefUtil_AddMovableReference
                  // -----------------------------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// This component-private `struct` template provides a metafunction that
/// defines a nested `type` typedef that, if `t_TYPE` is not a reference
/// type, is `MovableRef<t_TYPE>`.  Otherwise, if `t_TYPE` is a
/// specialization of `MovableRef`, `type` is the same as `t_TYPE`.
/// Otherwise, `type` is `t_TYPE&`.  This transformation reflects the
/// semantics of
/// _reference collapsing_ in section [dec.ref] of the standard.
template <class t_TYPE>
struct MovableRefUtil_AddMovableReference : bsl::add_rvalue_reference<t_TYPE> {
};

#else // if !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

template <>
struct MovableRefUtil_AddMovableReference<void> {
    // TYPES
    typedef void type;
};

template <>
struct MovableRefUtil_AddMovableReference<const void> {
    // TYPES
    typedef const void type;
};

template <>
struct MovableRefUtil_AddMovableReference<volatile void> {
    // TYPES
    typedef volatile void type;
};

template <>
struct MovableRefUtil_AddMovableReference<const volatile void> {
    // TYPES
    typedef const volatile void type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference {
    // TYPES
    typedef bslmf::MovableRef<t_TYPE> type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<t_TYPE&> {
    // TYPES
    typedef t_TYPE& type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<MovableRef<t_TYPE> > {
    // TYPES
    typedef bslmf::MovableRef<t_TYPE> type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<MovableRef<t_TYPE>&> {
    // TYPES
    typedef bslmf::MovableRef<t_TYPE> type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<const MovableRef<t_TYPE> > {
    // TYPES
    typedef bslmf::MovableRef<t_TYPE> type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<const MovableRef<t_TYPE>&> {
    // TYPES
    typedef bslmf::MovableRef<t_TYPE> type;
};

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_AddMovableReference<const volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

                         // ---------------------------
                         // struct MovableRefUtil_Decay
                         // ---------------------------

#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES

/// This component-private `struct` template provides a metafunction that
/// defines a nested `type` typedef that applies lvalue-to-rvalue,
/// array-to-pointer, and function-to-pointer conversions that occur when an
/// lvalue of type `t_TYPE` is used as an rvalue, and also removes `const`,
/// `volatile`, and reference qualifiers from class types in order to model
/// by-value argument passing.  For the purpose of this type trait,
/// `MovableRef<T>` is considered a (movable) reference-qualified `T`.
///
/// Formally, let `U` be `MovableRefUtil::RemoveReference<t_TYPE>::type`.
/// If `bsl::is_array<U>::value` is true, the member typedef `type` is
/// `bsl::remove_extent<U>::type *`.  If `bsl::is_function<U>::value` is
/// true, the member typedef `type` is `bsl::add_pointer<U>::type`.
/// Otherwise, the member typedef `type` is `bsl::remove_cv<U>::type`.
template <class t_TYPE>
struct MovableRefUtil_Decay : bsl::decay<t_TYPE> {
};

#elif !defined(BSLS_PLATFORM_CMP_IBM) || BSLS_PLATFORM_CMP_VERSION > 4097

///Implementation Note
///- - - - - - - - - -
// The following definition of 'MovableRefUtil_Decay' is for C++03 compilers,
// *except* versions of IBM XL C++ prior to 16.0.2.

template <class t_TYPE>
struct MovableRefUtil_Decay
: bsl::decay<typename MovableRefUtil_RemoveReference<t_TYPE>::type> {
};

#else

///Implementation Note
///- - - - - - - - - -
// The following implementation of 'MovableRefUtil_Decay' is exclusively for
// the IBM XL C++ line of compilers prior to version 16.0.2.  This line of
// compilers has a defect in which the compiler retains default-argument
// information in the type of functions that have default arguments.  If the
// program attempts to form a typedef to the type of a function with default
// arguments, the IBM XL C++ compiler rejects the typedef because it attempts
// to form it with default arguments.  Since default arguments cannot be
// specified anywhere except function declarations, compilation then fails.
//
// For example, the following code will be rejected:
//..
//  void f(int = 0);
//
//  template <class t_TYPE>
//  void g(t_TYPE)
//  {
//      typedef t_TYPE type; // ERROR: Default arguments cannot be specified
//                         //        in a 'typedef'.
//  }
//
//  void example()
//  {
//      g(f);              // ERROR: From the 'g' template instantiation here.
//  }
//..
// However, typedefs to *pointers* to such function types do not run afoul of
// this defect.  Fortunately, the specification of 'decay' requires
// transforming function types and reference-to-function types to
// pointer-to-function types.  So, with some careful metaprogramming, the
// following implementation avoids triggering this defect.

template <class t_TYPE, bool t_IS_FUNCTION = bsl::is_function<t_TYPE>::value>
struct MovableRefUtil_DecayImp;

template <class t_TYPE>
struct MovableRefUtil_DecayImp<t_TYPE, /* t_IS_FUNCTION */ false>
: bsl::decay<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_DecayImp<t_TYPE, /* t_IS_FUNCTION */ true> {
    typedef t_TYPE *type;
};

template <class t_TYPE>
struct MovableRefUtil_Decay : MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<t_TYPE&> : MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<MovableRef<t_TYPE> >
: MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<MovableRef<t_TYPE>&>
: MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<const MovableRef<t_TYPE> >
: MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<const MovableRef<t_TYPE>&>
: MovableRefUtil_DecayImp<t_TYPE> {
};

template <class t_TYPE>
struct MovableRefUtil_Decay<volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_Decay<volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_Decay<const volatile MovableRef<t_TYPE> >;
    // This partial 'struct' template specialization is not defined.

template <class t_TYPE>
struct MovableRefUtil_Decay<const volatile MovableRef<t_TYPE>&>;
    // This partial 'struct' template specialization is not defined.

#endif // !defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
