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>
133  requires __is_invocable_using<const decltype(__fn)&>
134  constexpr
135  function_ref(nontype_t<__fn>) noexcept
136  {
137  using _Fn = remove_cv_t<decltype(__fn)>;
138  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
139  static_assert(__fn != nullptr);
140 
141  _M_invoke = &_Invoker::template _S_nttp<__fn>;
142  _M_ptrs._M_obj = nullptr;
143  }
144 
145  /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
146  /// Bound object is object referenced by second parameter.
147  template<auto __fn, typename _Up, typename _Td = remove_reference_t<_Up>>
148  requires (!is_rvalue_reference_v<_Up&&>)
149  && __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV&>
150  constexpr
151  function_ref(nontype_t<__fn>, _Up&& __ref) noexcept
152  {
153  using _Fn = remove_cv_t<decltype(__fn)>;
154  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
155  static_assert(__fn != nullptr);
156 
157  if constexpr (is_member_pointer_v<_Fn>
158  && same_as<_Td, typename __inv_unwrap<_Td>::type>)
159  // N.B. invoking member pointer on lvalue produces the same effects,
160  // as invoking it on pointer to that lvalue.
161  _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
162  else
163  _M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>;
164  _M_init(std::addressof(__ref));
165  }
166 
167  /// Target object is equivalent to std::bind_front<_fn>(__ptr).
168  /// Bound object is object pointed by second parameter (if any).
169  template<auto __fn, typename _Td>
170  requires __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV*>
171  constexpr
172  function_ref(nontype_t<__fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
173  {
174  using _Fn = remove_cv_t<decltype(__fn)>;
175  if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
176  static_assert(__fn != nullptr);
177  if constexpr (is_member_pointer_v<_Fn>)
178  __glibcxx_assert(__ptr != nullptr);
179 
180  _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
181  _M_init(__ptr);
182  }
183 
184  template<typename _Tp>
185  requires (!is_same_v<_Tp, function_ref>)
186  && (!is_pointer_v<_Tp>) && (!__is_nontype_v<_Tp>)
187  function_ref&
188  operator=(_Tp) = delete;
189 
190  /** Invoke the target object.
191  *
192  * The bound object will be invoked using the supplied arguments,
193  * and as const or non-const, as dictated by the template arguments
194  * of the `function_ref` specialization.
195  */
196  _Res
197  operator()(_ArgTypes... __args) const noexcept(_Noex)
198  { return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); }
199 
200  private:
201  template<typename _Tp>
202  constexpr void
203  _M_init(_Tp* __ptr) noexcept
204  {
205  if constexpr (is_function_v<_Tp>)
206  _M_ptrs._M_func = reinterpret_cast<void(*)()>(__ptr);
207  else
208  _M_ptrs._M_obj = __ptr;
209  }
210 
211  typename _Invoker::__ptrs_func_t _M_invoke;
212  __polyfunc::_Ptrs _M_ptrs;
213  };
214 
215 #undef _GLIBCXX_MOF_CV
216 
217 _GLIBCXX_END_NAMESPACE_VERSION
218 } // namespace std
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