1 // Implementation of std::move_only_function -*- C++ -*-
3 // Copyright The GNU Toolchain Authors.
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)
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.
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.
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/>.
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}
30 #ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
31 #define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
33 #pragma GCC system_header
35 #include <bits/version.h>
37 #ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
39 #include <bits/invoke.h>
40 #include <bits/utility.h>
42 namespace std
_GLIBCXX_VISIBILITY(default)
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 template<typename
... _Signature
>
47 class move_only_function
; // not defined
49 /// @cond undocumented
53 _Mofunc_base() noexcept
57 _Mofunc_base(_Mofunc_base
&& __x
) noexcept
59 _M_manage
= std::__exchange(__x
._M_manage
, _S_empty
);
60 _M_manage(_M_storage
, &__x
._M_storage
);
63 template<typename _Tp
, typename
... _Args
>
65 _S_nothrow_init() noexcept
67 if constexpr (__stored_locally
<_Tp
>)
68 return is_nothrow_constructible_v
<_Tp
, _Args
...>;
72 template<typename _Tp
, typename
... _Args
>
74 _M_init(_Args
&&... __args
) noexcept(_S_nothrow_init
<_Tp
, _Args
...>())
76 if constexpr (__stored_locally
<_Tp
>)
77 ::new (_M_storage
._M_addr()) _Tp(std::forward
<_Args
>(__args
)...);
79 _M_storage
._M_p
= new _Tp(std::forward
<_Args
>(__args
)...);
81 _M_manage
= &_S_manage
<_Tp
>;
85 operator=(_Mofunc_base
&& __x
) noexcept
87 _M_manage(_M_storage
, nullptr);
88 _M_manage
= std::__exchange(__x
._M_manage
, _S_empty
);
89 _M_manage(_M_storage
, &__x
._M_storage
);
94 operator=(nullptr_t
) noexcept
96 _M_manage(_M_storage
, nullptr);
101 ~_Mofunc_base() { _M_manage(_M_storage
, nullptr); }
104 swap(_Mofunc_base
& __x
) noexcept
106 // Order of operations here is more efficient if __x is empty.
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
);
114 template<typename _Tp
, typename _Self
>
116 _S_access(_Self
* __self
) noexcept
118 if constexpr (__stored_locally
<remove_const_t
<_Tp
>>)
119 return static_cast<_Tp
*>(__self
->_M_storage
._M_addr());
121 return static_cast<_Tp
*>(__self
->_M_storage
._M_p
);
127 void* _M_addr() noexcept
{ return &_M_bytes
[0]; }
128 const void* _M_addr() const noexcept
{ return &_M_bytes
[0]; }
130 // We want to have enough space to store a simple delegate type.
131 struct _Delegate
{ void (_Storage::*__pfm
)(); _Storage
* __obj
; };
134 alignas(_Delegate
) alignas(void(*)())
135 unsigned char _M_bytes
[sizeof(_Delegate
)];
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
>;
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
;
148 // The no-op manager function for objects with no target.
149 static void _S_empty(_Storage
&, _Storage
*) noexcept
{ }
151 // The real manager function for a target object of type _Tp.
152 template<typename _Tp
>
154 _S_manage(_Storage
& __target
, _Storage
* __src
) noexcept
156 if constexpr (__stored_locally
<_Tp
>)
160 _Tp
* __rval
= static_cast<_Tp
*>(__src
->_M_addr());
161 ::new (__target
._M_addr()) _Tp(std::move(*__rval
));
165 static_cast<_Tp
*>(__target
._M_addr())->~_Tp();
170 __target
._M_p
= __src
->_M_p
;
172 delete static_cast<_Tp
*>(__target
._M_p
);
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;
186 namespace __detail::__variant
188 template<typename
> struct _Never_valueless_alt
; // see <variant>
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
...>>
196 } // namespace __detail::__variant
198 _GLIBCXX_END_NAMESPACE_VERSION
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"
215 #endif // __glibcxx_move_only_function
216 #endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H