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