libstdc++
funcref_impl.h
Go to the documentation of this file.
1 // Implementation of std::function_ref -*- 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/funcref_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 namespace std _GLIBCXX_VISIBILITY(default)
35 {
36 _GLIBCXX_BEGIN_NAMESPACE_VERSION
37 
38  /// @cond undocumented
39  namespace __polyfunc
40  {
41  template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
42  struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV
43  noexcept(_Noex)>
44  { using type = _Ret(_Args...) noexcept(_Noex); };
45 
46  template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
47  struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV&
48  noexcept(_Noex)>
49  { using type = _Ret(_Args...) noexcept(_Noex); };
50  } // namespace __polyfunc
51  /// @endcond
52 
53  /**
54  * @brief Non-owning polymorphic function wrapper.
55  * @ingroup functors
56  * @since C++26
57  * @headerfile functional
58  *
59  * The `std::function_ref` class template is a non-owning call wrapper,
60  * that refers to a bound object. Using function_ref outside of the lifetime
61  * of the bound object has undefined behavior.
62  *
63  * It supports const-qualification and no-throw guarantees. The
64  * qualifications and exception-specification of the signature are respected
65  * when invoking the reference function.
66  */
67  template<typename _Res, typename... _ArgTypes, bool _Noex>
68  class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
69  noexcept(_Noex)>
70  {
71  static_assert(
72  (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
73  "each parameter type must be a complete class");
74 
75  using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
76  using _Signature = _Invoker::_Signature;
77 
78  // [func.wrap.ref.ctor]/1 is-invokable-using
79  template<typename... _Tps>
80  static constexpr bool __is_invocable_using
81  = __conditional_t<_Noex,
82  is_nothrow_invocable_r<_Res, _Tps..., _ArgTypes...>,
83  is_invocable_r<_Res, _Tps..., _ArgTypes...>>::value;
84 
85  public:
86  /// Target and bound object is function pointed by parameter.
87  template<typename _Fn>
88  requires is_function_v<_Fn> && __is_invocable_using<_Fn*>
89  function_ref(_Fn* __fn) noexcept
90  {
91  __glibcxx_assert(__fn != nullptr);
92  _M_invoke = _Invoker::template _S_ptrs<_Fn*>();
93  _M_init(__fn);
94  }
95 
96  /// Target and bound object is object referenced by parameter.
97  template<typename _Fn, typename _Vt = remove_reference_t<_Fn>>
98  requires (!is_same_v<remove_cv_t<_Vt>, function_ref>)
99  && (!is_member_pointer_v<_Vt>)
100  // We deviate from standard by having this condition, that forces
101  // function references to use _Fn* constructors. This simplies
102  // implementation and provide better diagnostic when used in
103  // constant expression (above constructor is not constexpr).
104  && (!is_function_v<_Vt>)
105  && __is_invocable_using<_Vt _GLIBCXX_MOF_CV&>
106  constexpr
107  function_ref(_Fn&& __f) noexcept
108  {
109  using _Fd = remove_cv_t<_Vt>;
110  if constexpr (__is_std_op_wrapper<_Fd>)
111  {
112  _M_invoke = _Invoker::template _S_nttp<_Fd{}>;
113  _M_ptrs._M_obj = nullptr;
114  }
115  else if constexpr (requires (_ArgTypes&&... __args) {
116  _Fd::operator()(std::forward<_ArgTypes>(__args)...);
117  })
118  {
119  _M_invoke = _Invoker::template _S_static<_Fd>;
120  _M_ptrs._M_obj = nullptr;
121  }
122  else
123  {
124  _M_invoke = _Invoker::template _S_ptrs<_Vt _GLIBCXX_MOF_CV&>();
125  _M_init(std::addressof(__f));
126  }
127  }
128 
129  // _GLIBCXX_RESOLVE_LIB_DEFECTS
130  // 4256. Incorrect constrains for function_ref constructors from nontype
131  /// Target object is __fn. There is no bound object.
132  template<auto __fn, typename _Fn>
133  requires __is_invocable_using<const _Fn&>
134  constexpr
135  function_ref(constant_wrapper<__fn, _Fn>) noexcept
136  {
137  if constexpr (sizeof...(_ArgTypes) > 0)
138  if constexpr ((... && _ConstExprParam<remove_cvref_t<_ArgTypes>>))
139  static_assert(!requires {
140  typename constant_wrapper<
141  std::__invoke(__fn, remove_cvref_t<_ArgTypes>::value...)>;
142  }, "cw<fn>(args...) should be equivalent to fn(args...)");
143 
144  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
145  static_assert(__fn != nullptr);
146 
147  _M_invoke = &_Invoker::template _S_nttp<__fn>;
148  _M_ptrs._M_obj = nullptr;
149  }
150 
151  /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
152  /// Bound object is object referenced by second parameter.
153  template<auto __fn, typename _Fn, typename _Up,
154  typename _Td = remove_reference_t<_Up>>
155  requires (!is_rvalue_reference_v<_Up&&>)
156  && __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV&>
157  constexpr
158  function_ref(constant_wrapper<__fn, _Fn>, _Up&& __ref) noexcept
159  {
160  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
161  static_assert(__fn != nullptr);
162 
163  if constexpr (is_member_pointer_v<_Fn>
164  && same_as<_Td, typename __inv_unwrap<_Td>::type>)
165  // N.B. invoking member pointer on lvalue produces the same effects,
166  // as invoking it on pointer to that lvalue.
167  _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
168  else
169  _M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>;
170  _M_init(std::addressof(__ref));
171  }
172 
173  /// Target object is equivalent to std::bind_front<_fn>(__ptr).
174  /// Bound object is object pointed by second parameter (if any).
175  template<auto __fn, typename _Fn, typename _Td>
176  requires __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV*>
177  constexpr
178  function_ref(constant_wrapper<__fn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
179  {
180  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
181  static_assert(__fn != nullptr);
182  if constexpr (is_member_pointer_v<_Fn>)
183  __glibcxx_assert(__ptr != nullptr);
184 
185  _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
186  _M_init(__ptr);
187  }
188 
189  template<typename _Tp>
190  requires (!is_same_v<_Tp, function_ref>) && (!is_pointer_v<_Tp>)
191  && (!__is_constant_wrapper_v<_Tp>)
192  function_ref&
193  operator=(_Tp) = delete;
194 
195  /** Invoke the target object.
196  *
197  * The bound object will be invoked using the supplied arguments,
198  * and as const or non-const, as dictated by the template arguments
199  * of the `function_ref` specialization.
200  */
201  _Res
202  operator()(_ArgTypes... __args) const noexcept(_Noex)
203  { return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); }
204 
205  private:
206  template<typename _Tp>
207  constexpr void
208  _M_init(_Tp* __ptr) noexcept
209  {
210  if constexpr (is_function_v<_Tp>)
211  _M_ptrs._M_func = reinterpret_cast<void(*)()>(__ptr);
212  else
213  _M_ptrs._M_obj = __ptr;
214  }
215 
216  typename _Invoker::__ptrs_func_t _M_invoke;
217  __polyfunc::_Ptrs _M_ptrs;
218  };
219 
220 #undef _GLIBCXX_MOF_CV
221 
222 _GLIBCXX_END_NAMESPACE_VERSION
223 } // namespace std
requires requires
Definition: complex:1948
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition: type_traits:1892
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition: invoke.h:92
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition: move.h:176
ISO C++ entities toplevel namespace is std.
concept same_as
[concept.same], concept same_as
Definition: concepts:65
requires is_function_v< _Fn > &&__is_invocable_using< _Fn * > function_ref(_Fn *__fn) noexcept
Target and bound object is function pointed by parameter.
Definition: funcref_impl.h:89
requires(!is_same_v< remove_cv_t< _Vt >, function_ref >) &&(!is_member_pointer_v< _Vt >) &&(!is_function_v< _Vt >) &&__is_invocable_using< _Vt _GLIBCXX_MOF_CV & > const expr function_ref(_Fn &&__f) noexcept
Target and bound object is object referenced by parameter.
Definition: funcref_impl.h:98