(root)/
gcc-13.2.0/
libstdc++-v3/
include/
bits/
move_only_function.h
       1  // Implementation of std::move_only_function -*- C++ -*-
       2  
       3  // Copyright The GNU Toolchain Authors.
       4  //
       5  // This file is part of the GNU ISO C++ Library.  This library is free
       6  // software; you can redistribute it and/or modify it under the
       7  // terms of the GNU General Public License as published by the
       8  // Free Software Foundation; either version 3, or (at your option)
       9  // any later version.
      10  
      11  // This library is distributed in the hope that it will be useful,
      12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  // GNU General Public License for more details.
      15  
      16  // Under Section 7 of GPL version 3, you are granted additional
      17  // permissions described in the GCC Runtime Library Exception, version
      18  // 3.1, as published by the Free Software Foundation.
      19  
      20  // You should have received a copy of the GNU General Public License and
      21  // a copy of the GCC Runtime Library Exception along with this program;
      22  // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23  // <http://www.gnu.org/licenses/>.
      24  
      25  /** @file include/bits/move_only_function.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{functional}
      28   */
      29  
      30  #ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
      31  #define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  #if __cplusplus > 202002L
      36  
      37  #include <bits/invoke.h>
      38  #include <bits/utility.h>
      39  
      40  namespace std _GLIBCXX_VISIBILITY(default)
      41  {
      42  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      43  
      44  #define __cpp_lib_move_only_function 202110L
      45  
      46    template<typename... _Signature>
      47      class move_only_function; // not defined
      48  
      49    /// @cond undocumented
      50    class _Mofunc_base
      51    {
      52    protected:
      53      _Mofunc_base() noexcept
      54      : _M_manage(_S_empty)
      55      { }
      56  
      57      _Mofunc_base(_Mofunc_base&& __x) noexcept
      58      {
      59        _M_manage = std::__exchange(__x._M_manage, _S_empty);
      60        _M_manage(_M_storage, &__x._M_storage);
      61      }
      62  
      63      template<typename _Tp, typename... _Args>
      64        static constexpr bool
      65        _S_nothrow_init() noexcept
      66        {
      67  	if constexpr (__stored_locally<_Tp>)
      68  	  return is_nothrow_constructible_v<_Tp, _Args...>;
      69  	return false;
      70        }
      71  
      72      template<typename _Tp, typename... _Args>
      73        void
      74        _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
      75        {
      76  	if constexpr (__stored_locally<_Tp>)
      77  	  ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...);
      78  	else
      79  	  _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...);
      80  
      81  	_M_manage = &_S_manage<_Tp>;
      82        }
      83  
      84      _Mofunc_base&
      85      operator=(_Mofunc_base&& __x) noexcept
      86      {
      87        _M_manage(_M_storage, nullptr);
      88        _M_manage = std::__exchange(__x._M_manage, _S_empty);
      89        _M_manage(_M_storage, &__x._M_storage);
      90        return *this;
      91      }
      92  
      93      _Mofunc_base&
      94      operator=(nullptr_t) noexcept
      95      {
      96        _M_manage(_M_storage, nullptr);
      97        _M_manage = _S_empty;
      98        return *this;
      99      }
     100  
     101      ~_Mofunc_base() { _M_manage(_M_storage, nullptr); }
     102  
     103      void
     104      swap(_Mofunc_base& __x) noexcept
     105      {
     106        // Order of operations here is more efficient if __x is empty.
     107        _Storage __s;
     108        __x._M_manage(__s, &__x._M_storage);
     109        _M_manage(__x._M_storage, &_M_storage);
     110        __x._M_manage(_M_storage, &__s);
     111        std::swap(_M_manage, __x._M_manage);
     112      }
     113  
     114      template<typename _Tp, typename _Self>
     115        static _Tp*
     116        _S_access(_Self* __self) noexcept
     117        {
     118  	if constexpr (__stored_locally<remove_const_t<_Tp>>)
     119  	  return static_cast<_Tp*>(__self->_M_storage._M_addr());
     120  	else
     121  	  return static_cast<_Tp*>(__self->_M_storage._M_p);
     122        }
     123  
     124    private:
     125      struct _Storage
     126      {
     127        void*       _M_addr() noexcept       { return &_M_bytes[0]; }
     128        const void* _M_addr() const noexcept { return &_M_bytes[0]; }
     129  
     130        // We want to have enough space to store a simple delegate type.
     131        struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
     132        union {
     133  	void* _M_p;
     134  	alignas(_Delegate) alignas(void(*)())
     135  	  unsigned char _M_bytes[sizeof(_Delegate)];
     136        };
     137      };
     138  
     139      template<typename _Tp>
     140        static constexpr bool __stored_locally
     141  	= sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage)
     142  	    && is_nothrow_move_constructible_v<_Tp>;
     143  
     144      // A function that either destroys the target object stored in __target,
     145      // or moves the target object from *__src to __target.
     146      using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept;
     147  
     148      // The no-op manager function for objects with no target.
     149      static void _S_empty(_Storage&, _Storage*) noexcept { }
     150  
     151      // The real manager function for a target object of type _Tp.
     152      template<typename _Tp>
     153        static void
     154        _S_manage(_Storage& __target, _Storage* __src) noexcept
     155        {
     156  	if constexpr (__stored_locally<_Tp>)
     157  	  {
     158  	    if (__src)
     159  	      {
     160  		_Tp* __rval = static_cast<_Tp*>(__src->_M_addr());
     161  		::new (__target._M_addr()) _Tp(std::move(*__rval));
     162  		__rval->~_Tp();
     163  	      }
     164  	    else
     165  	      static_cast<_Tp*>(__target._M_addr())->~_Tp();
     166  	  }
     167  	else
     168  	  {
     169  	    if (__src)
     170  	      __target._M_p = __src->_M_p;
     171  	    else
     172  	      delete static_cast<_Tp*>(__target._M_p);
     173  	  }
     174        }
     175  
     176      _Storage _M_storage;
     177      _Manager _M_manage;
     178    };
     179  
     180    template<typename _Tp>
     181      inline constexpr bool __is_move_only_function_v = false;
     182    template<typename _Tp>
     183      constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true;
     184    /// @endcond
     185  
     186    namespace __detail::__variant
     187    {
     188      template<typename> struct _Never_valueless_alt; // see <variant>
     189  
     190      // Provide the strong exception-safety guarantee when emplacing a
     191      // move_only_function into a variant.
     192      template<typename... _Signature>
     193        struct _Never_valueless_alt<std::move_only_function<_Signature...>>
     194        : true_type
     195        { };
     196    }  // namespace __detail::__variant
     197  
     198  _GLIBCXX_END_NAMESPACE_VERSION
     199  } // namespace std
     200  
     201  #include "mofunc_impl.h"
     202  #define _GLIBCXX_MOF_CV const
     203  #include "mofunc_impl.h"
     204  #define _GLIBCXX_MOF_REF &
     205  #include "mofunc_impl.h"
     206  #define _GLIBCXX_MOF_REF &&
     207  #include "mofunc_impl.h"
     208  #define _GLIBCXX_MOF_CV const
     209  #define _GLIBCXX_MOF_REF &
     210  #include "mofunc_impl.h"
     211  #define _GLIBCXX_MOF_CV const
     212  #define _GLIBCXX_MOF_REF &&
     213  #include "mofunc_impl.h"
     214  
     215  #endif // C++23
     216  #endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H