libstdc++
mofunc_impl.h
Go to the documentation of this file.
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/mofunc_impl.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_MOF_CV
31# define _GLIBCXX_MOF_CV
32#endif
33
34#ifdef _GLIBCXX_MOF_REF
35# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
36#else
37# define _GLIBCXX_MOF_REF
38# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
39#endif
40
41#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
42
43namespace std _GLIBCXX_VISIBILITY(default)
44{
45_GLIBCXX_BEGIN_NAMESPACE_VERSION
46
47 /**
48 * @brief Polymorphic function wrapper.
49 * @ingroup functors
50 * @since C++23
51 * @headerfile functional
52 *
53 * The `std::move_only_function` class template is a call wrapper similar
54 * to * `std::function`, but does not require the stored target function
55 * to be copyable.
56 *
57 * It also supports const-qualification, ref-qualification, and
58 * no-throw guarantees. The qualifications and exception-specification
59 * of the `move_only_function::operator()` member function are respected
60 * when invoking the target function.
61 *
62 */
63 template<typename _Res, typename... _ArgTypes, bool _Noex>
64 class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
65 _GLIBCXX_MOF_REF noexcept(_Noex)>
66 : _Mofunc_base
67 {
68 template<typename _Tp>
69 using __callable
70 = __conditional_t<_Noex,
71 is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
72 is_invocable_r<_Res, _Tp, _ArgTypes...>>;
73
74 // [func.wrap.mov.con]/1 is-callable-from<VT>
75 template<typename _Vt>
76 static constexpr bool __is_callable_from
77 = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
78 __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
79
80 public:
81 using result_type = _Res;
82
83 /// Creates an empty object.
84 move_only_function() noexcept { }
85
86 /// Creates an empty object.
87 move_only_function(nullptr_t) noexcept { }
88
89 /// Moves the target object, leaving the source empty.
90 move_only_function(move_only_function&& __x) noexcept
91 : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
92 _M_invoke(std::__exchange(__x._M_invoke, nullptr))
93 { }
94
95 /// Stores a target object initialized from the argument.
96 template<typename _Fn, typename _Vt = decay_t<_Fn>>
97 requires (!is_same_v<_Vt, move_only_function>)
98 && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
99 move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
100 {
101 if constexpr (is_function_v<remove_pointer_t<_Vt>>
102 || is_member_pointer_v<_Vt>
103 || __is_move_only_function_v<_Vt>)
104 {
105 if (__f == nullptr)
106 return;
107 }
108 _M_init<_Vt>(std::forward<_Fn>(__f));
109 _M_invoke = &_S_invoke<_Vt>;
110 }
111
112 /// Stores a target object initialized from the arguments.
113 template<typename _Tp, typename... _Args>
114 requires is_constructible_v<_Tp, _Args...>
115 && __is_callable_from<_Tp>
116 explicit
117 move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
118 noexcept(_S_nothrow_init<_Tp, _Args...>())
119 : _M_invoke(&_S_invoke<_Tp>)
120 {
121 static_assert(is_same_v<decay_t<_Tp>, _Tp>);
122 _M_init<_Tp>(std::forward<_Args>(__args)...);
123 }
124
125 /// Stores a target object initialized from the arguments.
126 template<typename _Tp, typename _Up, typename... _Args>
127 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
128 && __is_callable_from<_Tp>
129 explicit
130 move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
131 _Args&&... __args)
132 noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
133 : _M_invoke(&_S_invoke<_Tp>)
134 {
135 static_assert(is_same_v<decay_t<_Tp>, _Tp>);
136 _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
137 }
138
139 /// Stores a new target object, leaving `x` empty.
140 move_only_function&
141 operator=(move_only_function&& __x) noexcept
142 {
143 _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
144 _M_invoke = std::__exchange(__x._M_invoke, nullptr);
145 return *this;
146 }
147
148 /// Destroys the target object (if any).
149 move_only_function&
150 operator=(nullptr_t) noexcept
151 {
152 _Mofunc_base::operator=(nullptr);
153 _M_invoke = nullptr;
154 return *this;
155 }
156
157 /// Stores a new target object, initialized from the argument.
158 template<typename _Fn>
159 requires is_constructible_v<move_only_function, _Fn>
160 move_only_function&
161 operator=(_Fn&& __f)
162 noexcept(is_nothrow_constructible_v<move_only_function, _Fn>)
163 {
164 move_only_function(std::forward<_Fn>(__f)).swap(*this);
165 return *this;
166 }
167
168 ~move_only_function() = default;
169
170 /// True if a target object is present, false otherwise.
171 explicit operator bool() const noexcept { return _M_invoke != nullptr; }
172
173 /** Invoke the target object.
174 *
175 * The target object will be invoked using the supplied arguments,
176 * and as an lvalue or rvalue, and as const or non-const, as dictated
177 * by the template arguments of the `move_only_function` specialization.
178 *
179 * @pre Must not be empty.
180 */
181 _Res
182 operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
183 {
184 __glibcxx_assert(*this != nullptr);
185 return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
186 }
187
188 /// Exchange the target objects (if any).
189 void
190 swap(move_only_function& __x) noexcept
191 {
192 _Mofunc_base::swap(__x);
193 std::swap(_M_invoke, __x._M_invoke);
194 }
195
196 /// Exchange the target objects (if any).
197 friend void
198 swap(move_only_function& __x, move_only_function& __y) noexcept
199 { __x.swap(__y); }
200
201 /// Check for emptiness by comparing with `nullptr`.
202 friend bool
203 operator==(const move_only_function& __x, nullptr_t) noexcept
204 { return __x._M_invoke == nullptr; }
205
206 private:
207 template<typename _Tp>
208 using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
209
210 using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
211 __param_t<_ArgTypes>...) noexcept(_Noex);
212
213 template<typename _Tp>
214 static _Res
215 _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
216 __param_t<_ArgTypes>... __args) noexcept(_Noex)
217 {
218 using _TpCv = _Tp _GLIBCXX_MOF_CV;
219 using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
220 return std::__invoke_r<_Res>(
221 std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
222 std::forward<__param_t<_ArgTypes>>(__args)...);
223 }
224
225 _Invoker _M_invoke = nullptr;
226 };
227
228#undef _GLIBCXX_MOF_CV_REF
229#undef _GLIBCXX_MOF_CV
230#undef _GLIBCXX_MOF_REF
231#undef _GLIBCXX_MOF_INV_QUALS
232
233_GLIBCXX_END_NAMESPACE_VERSION
234} // namespace std
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:77
ISO C++ entities toplevel namespace is std.
initializer_list
std::is_invocable_r
Definition: type_traits:3091
std::is_nothrow_invocable_r
Definition: type_traits:3128
move_only_function & operator=(nullptr_t) noexcept
Destroys the target object (if any).
Definition: mofunc_impl.h:150
_Res operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV noexcept(_Noex)
Definition: mofunc_impl.h:182
move_only_function(_Fn &&__f) noexcept(_S_nothrow_init< _Vt, _Fn >())
Stores a target object initialized from the argument.
Definition: mofunc_impl.h:99
friend void swap(move_only_function &__x, move_only_function &__y) noexcept
Exchange the target objects (if any).
Definition: mofunc_impl.h:198
move_only_function & operator=(move_only_function &&__x) noexcept
Stores a new target object, leaving x empty.
Definition: mofunc_impl.h:141
move_only_function & operator=(_Fn &&__f) noexcept(is_nothrow_constructible_v< move_only_function, _Fn >)
Stores a new target object, initialized from the argument.
Definition: mofunc_impl.h:161
friend bool operator==(const move_only_function &__x, nullptr_t) noexcept
Check for emptiness by comparing with nullptr.
Definition: mofunc_impl.h:203
void swap(move_only_function &__x) noexcept
Exchange the target objects (if any).
Definition: mofunc_impl.h:190
move_only_function(in_place_type_t< _Tp >, initializer_list< _Up > __il, _Args &&... __args) noexcept(_S_nothrow_init< _Tp, initializer_list< _Up > &, _Args... >())
Stores a target object initialized from the arguments.
Definition: mofunc_impl.h:130
move_only_function(in_place_type_t< _Tp >, _Args &&... __args) noexcept(_S_nothrow_init< _Tp, _Args... >())
Stores a target object initialized from the arguments.
Definition: mofunc_impl.h:117
move_only_function(move_only_function &&__x) noexcept
Moves the target object, leaving the source empty.
Definition: mofunc_impl.h:90