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 
43 namespace 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
209  = __conditional_t<is_trivially_copyable_v<_Tp>
210  && sizeof(_Tp) <= sizeof(long),
211  _Tp, _Tp&&>;
212 
213  using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
214  __param_t<_ArgTypes>...) noexcept(_Noex);
215 
216  template<typename _Tp>
217  static _Res
218  _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
219  __param_t<_ArgTypes>... __args) noexcept(_Noex)
220  {
221  using _TpCv = _Tp _GLIBCXX_MOF_CV;
222  using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
223  return std::__invoke_r<_Res>(
224  std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
225  std::forward<__param_t<_ArgTypes>>(__args)...);
226  }
227 
228  _Invoker _M_invoke = nullptr;
229  };
230 
231 #undef _GLIBCXX_MOF_CV_REF
232 #undef _GLIBCXX_MOF_CV
233 #undef _GLIBCXX_MOF_REF
234 #undef _GLIBCXX_MOF_INV_QUALS
235 
236 _GLIBCXX_END_NAMESPACE_VERSION
237 } // namespace std
typename remove_pointer< _Tp >::type remove_pointer_t
Alias template for remove_pointer.
Definition: type_traits:2084
typename decay< _Tp >::type decay_t
Alias template for decay.
Definition: type_traits:2610
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:77
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
ISO C++ entities toplevel namespace is std.
initializer_list
std::is_invocable_r
Definition: type_traits:3052
std::is_nothrow_invocable_r
Definition: type_traits:3092
move_only_function(move_only_function &&__x) noexcept
Moves the target object, leaving the source empty.
Definition: mofunc_impl.h:90
requires(!is_same_v< _Vt, move_only_function >) &&(!__is_in_place_type_v< _Vt >) &&__is_callable_from< _Vt > move_only_function(_Fn &&__f) noexcept(_S_nothrow_init< _Vt, _Fn >())
Stores a target object initialized from the argument.
Definition: mofunc_impl.h:97