libstdc++
move.h
Go to the documentation of this file.
00001 // Move, forward and identity for C++11 + swap -*- C++ -*-
00002 
00003 // Copyright (C) 2007-2018 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/move.h
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{utility}
00028  */
00029 
00030 #ifndef _MOVE_H
00031 #define _MOVE_H 1
00032 
00033 #include <bits/c++config.h>
00034 #include <bits/concept_check.h>
00035 
00036 namespace std _GLIBCXX_VISIBILITY(default)
00037 {
00038 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00039 
00040   // Used, in C++03 mode too, by allocators, etc.
00041   /**
00042    *  @brief Same as C++11 std::addressof
00043    *  @ingroup utilities
00044    */
00045   template<typename _Tp>
00046     inline _GLIBCXX_CONSTEXPR _Tp*
00047     __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
00048     { return __builtin_addressof(__r); }
00049 
00050 #if __cplusplus >= 201103L
00051 
00052 _GLIBCXX_END_NAMESPACE_VERSION
00053 } // namespace
00054 
00055 #include <type_traits> // Brings in std::declval too.
00056 
00057 namespace std _GLIBCXX_VISIBILITY(default)
00058 {
00059 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00060 
00061   /**
00062    *  @addtogroup utilities
00063    *  @{
00064    */
00065 
00066   /**
00067    *  @brief  Forward an lvalue.
00068    *  @return The parameter cast to the specified type.
00069    *
00070    *  This function is used to implement "perfect forwarding".
00071    */
00072   template<typename _Tp>
00073     constexpr _Tp&&
00074     forward(typename std::remove_reference<_Tp>::type& __t) noexcept
00075     { return static_cast<_Tp&&>(__t); }
00076 
00077   /**
00078    *  @brief  Forward an rvalue.
00079    *  @return The parameter cast to the specified type.
00080    *
00081    *  This function is used to implement "perfect forwarding".
00082    */
00083   template<typename _Tp>
00084     constexpr _Tp&&
00085     forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
00086     {
00087       static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
00088                     " substituting _Tp is an lvalue reference type");
00089       return static_cast<_Tp&&>(__t);
00090     }
00091 
00092   /**
00093    *  @brief  Convert a value to an rvalue.
00094    *  @param  __t  A thing of arbitrary type.
00095    *  @return The parameter cast to an rvalue-reference to allow moving it.
00096   */
00097   template<typename _Tp>
00098     constexpr typename std::remove_reference<_Tp>::type&&
00099     move(_Tp&& __t) noexcept
00100     { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
00101 
00102 
00103   template<typename _Tp>
00104     struct __move_if_noexcept_cond
00105     : public __and_<__not_<is_nothrow_move_constructible<_Tp>>,
00106                     is_copy_constructible<_Tp>>::type { };
00107 
00108   /**
00109    *  @brief  Conditionally convert a value to an rvalue.
00110    *  @param  __x  A thing of arbitrary type.
00111    *  @return The parameter, possibly cast to an rvalue-reference.
00112    *
00113    *  Same as std::move unless the type's move constructor could throw and the
00114    *  type is copyable, in which case an lvalue-reference is returned instead.
00115    */
00116   template<typename _Tp>
00117     constexpr typename
00118     conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
00119     move_if_noexcept(_Tp& __x) noexcept
00120     { return std::move(__x); }
00121 
00122   // declval, from type_traits.
00123 
00124 #if __cplusplus > 201402L
00125   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00126   // 2296. std::addressof should be constexpr
00127 # define __cpp_lib_addressof_constexpr 201603
00128 #endif
00129   /**
00130    *  @brief Returns the actual address of the object or function
00131    *         referenced by r, even in the presence of an overloaded
00132    *         operator&.
00133    *  @param  __r  Reference to an object or function.
00134    *  @return   The actual address.
00135   */
00136   template<typename _Tp>
00137     inline _GLIBCXX17_CONSTEXPR _Tp*
00138     addressof(_Tp& __r) noexcept
00139     { return std::__addressof(__r); }
00140 
00141   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00142   // 2598. addressof works on temporaries
00143   template<typename _Tp>
00144     const _Tp* addressof(const _Tp&&) = delete;
00145 
00146   // C++11 version of std::exchange for internal use.
00147   template <typename _Tp, typename _Up = _Tp>
00148     inline _Tp
00149     __exchange(_Tp& __obj, _Up&& __new_val)
00150     {
00151       _Tp __old_val = std::move(__obj);
00152       __obj = std::forward<_Up>(__new_val);
00153       return __old_val;
00154     }
00155 
00156   /// @} group utilities
00157 
00158 #define _GLIBCXX_MOVE(__val) std::move(__val)
00159 #define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
00160 #else
00161 #define _GLIBCXX_MOVE(__val) (__val)
00162 #define _GLIBCXX_FORWARD(_Tp, __val) (__val)
00163 #endif
00164 
00165   /**
00166    *  @addtogroup utilities
00167    *  @{
00168    */
00169 
00170   /**
00171    *  @brief Swaps two values.
00172    *  @param  __a  A thing of arbitrary type.
00173    *  @param  __b  Another thing of arbitrary type.
00174    *  @return   Nothing.
00175   */
00176   template<typename _Tp>
00177     inline
00178 #if __cplusplus >= 201103L
00179     typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
00180                               is_move_constructible<_Tp>,
00181                               is_move_assignable<_Tp>>::value>::type
00182     swap(_Tp& __a, _Tp& __b)
00183     noexcept(__and_<is_nothrow_move_constructible<_Tp>,
00184                     is_nothrow_move_assignable<_Tp>>::value)
00185 #else
00186     void
00187     swap(_Tp& __a, _Tp& __b)
00188 #endif
00189     {
00190       // concept requirements
00191       __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
00192 
00193       _Tp __tmp = _GLIBCXX_MOVE(__a);
00194       __a = _GLIBCXX_MOVE(__b);
00195       __b = _GLIBCXX_MOVE(__tmp);
00196     }
00197 
00198   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00199   // DR 809. std::swap should be overloaded for array types.
00200   /// Swap the contents of two arrays.
00201   template<typename _Tp, size_t _Nm>
00202     inline
00203 #if __cplusplus >= 201103L
00204     typename enable_if<__is_swappable<_Tp>::value>::type
00205     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
00206     noexcept(__is_nothrow_swappable<_Tp>::value)
00207 #else
00208     void
00209     swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
00210 #endif
00211     {
00212       for (size_t __n = 0; __n < _Nm; ++__n)
00213         swap(__a[__n], __b[__n]);
00214     }
00215 
00216   /// @} group utilities
00217 _GLIBCXX_END_NAMESPACE_VERSION
00218 } // namespace
00219 
00220 #endif /* _MOVE_H */