Remove some checks of .empty()
[external/binutils.git] / gdb / gdbsupport / function-view.h
1 /* Copyright (C) 2017-2019 Free Software Foundation, Inc.
2
3    This file is part of GDB.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #ifndef COMMON_FUNCTION_VIEW_H
19 #define COMMON_FUNCTION_VIEW_H
20
21 /* function_view is a polymorphic type-erasing wrapper class that
22    encapsulates a non-owning reference to arbitrary callable objects.
23
24    A way to put it is that function_view is to std::function like
25    std::string_view is to std::string.  While std::function stores a
26    type-erased callable object internally, function_view holds a
27    type-erased reference to an external callable object.
28
29    This is meant to be used as callback type of a function that:
30
31      #1 - Takes a callback as parameter.
32
33      #2 - Wants to support arbitrary callable objects as callback type
34           (e.g., stateful function objects, lambda closures, free
35           functions).
36
37      #3 - Does not store the callback anywhere; instead the function
38           just calls the callback directly or forwards it to some
39           other function that calls it.
40
41      #4 - Can't be, or we don't want it to be, a template function
42           with the callable type as template parameter.  For example,
43           when the callback is a parameter of a virtual member
44           function, or when putting the function template in a header
45           would expose too much implementation detail.
46
47    Note that the C-style "function pointer" + "void *data" callback
48    parameter idiom fails requirement #2 above.  Please don't add new
49    uses of that idiom.  I.e., something like this wouldn't work;
50
51     typedef bool (iterate_over_foos_cb) (foo *f, void *user_data),
52     void iterate_over_foos (iterate_over_foos_cb *callback, void *user_data);
53
54     foo *find_foo_by_type (int type)
55     {
56       foo *found = nullptr;
57
58       iterate_over_foos ([&] (foo *f, void *data)
59         {
60           if (foo->type == type)
61             {
62               found = foo;
63               return true; // stop iterating
64             }
65           return false; // continue iterating
66         }, NULL);
67
68       return found;
69     }
70
71    The above wouldn't compile, because lambdas with captures can't be
72    implicitly converted to a function pointer (because a capture means
73    some context data must be passed to the lambda somehow).
74
75    C++11 gave us std::function as type-erased wrapper around arbitrary
76    callables, however, std::function is not an ideal fit for transient
77    callbacks such as the use case above.  For this use case, which is
78    quite pervasive, a function_view is a better choice, because while
79    function_view is light and does not require any heap allocation,
80    std::function is a heavy-weight object with value semantics that
81    generally requires a heap allocation on construction/assignment of
82    the target callable.  In addition, while it is possible to use
83    std::function in such a way that avoids most of the overhead by
84    making sure to only construct it with callables of types that fit
85    std::function's small object optimization, such as function
86    pointers and std::reference_wrapper callables, that is quite
87    inconvenient in practice, because restricting to free-function
88    callables would imply no state/capture/closure, which we need in
89    most cases, and std::reference_wrapper implies remembering to use
90    std::ref/std::cref where the callable is constructed, with the
91    added inconvenience that std::ref/std::cref have deleted rvalue-ref
92    overloads, meaning you can't use unnamed/temporary lambdas with
93    them.
94
95    Note that because function_view is a non-owning view of a callable,
96    care must be taken to ensure that the callable outlives the
97    function_view that calls it.  This is not really a problem for the
98    use case function_view is intended for, such as passing a temporary
99    function object / lambda to a function that accepts a callback,
100    because in those cases, the temporary is guaranteed to be live
101    until the called function returns.
102
103    Calling a function_view with no associated target is undefined,
104    unlike with std::function, which throws std::bad_function_call.
105    This is by design, to avoid the otherwise necessary NULL check in
106    function_view::operator().
107
108    Since function_view objects are small (a pair of pointers), they
109    should generally be passed around by value.
110
111    Usage:
112
113    Given this function that accepts a callback:
114
115     void
116     iterate_over_foos (gdb::function_view<void (foo *)> callback)
117     {
118        for (auto &foo : foos)
119          callback (&foo);
120     }
121
122    you can call it like this, passing a lambda as callback:
123
124     iterate_over_foos ([&] (foo *f)
125       {
126         process_one_foo (f);
127       });
128
129    or like this, passing a function object as callback:
130
131     struct function_object
132     {
133       void operator() (foo *f)
134       {
135         if (s->check ())
136           process_one_foo (f);
137       }
138
139       // some state
140       state *s;
141     };
142
143     state mystate;
144     function_object matcher {&mystate};
145     iterate_over_foos (matcher);
146
147   or like this, passing a function pointer as callback:
148
149     iterate_over_foos (process_one_foo);
150
151   You can find unit tests covering the whole API in
152   unittests/function-view-selftests.c.  */
153
154 namespace gdb {
155
156 namespace fv_detail {
157 /* Bits shared by all function_view instantiations that do not depend
158    on the template parameters.  */
159
160 /* Storage for the erased callable.  This is a union in order to be
161    able to save both a function object (data) pointer or a function
162    pointer without triggering undefined behavior.  */
163 union erased_callable
164 {
165   /* For function objects.  */
166   void *data;
167
168     /* For function pointers.  */
169   void (*fn) ();
170 };
171
172 } /* namespace fv_detail */
173
174 /* Use partial specialization to get access to the callable's
175    signature. */
176 template<class Signature>
177 struct function_view;
178
179 template<typename Res, typename... Args>
180 class function_view<Res (Args...)>
181 {
182   template<typename From, typename To>
183   using CompatibleReturnType
184     = Or<std::is_void<To>,
185          std::is_same<From, To>,
186          std::is_convertible<From, To>>;
187
188   /* True if Func can be called with Args, and either the result is
189      Res, convertible to Res or Res is void.  */
190   template<typename Callable,
191            typename Res2 = typename std::result_of<Callable &(Args...)>::type>
192   struct IsCompatibleCallable : CompatibleReturnType<Res2, Res>
193   {};
194
195   /* True if Callable is a function_view.  Used to avoid hijacking the
196      copy ctor.  */
197   template <typename Callable>
198   struct IsFunctionView
199     : std::is_same<function_view, typename std::decay<Callable>::type>
200   {};
201
202  public:
203
204   /* NULL by default.  */
205   constexpr function_view () noexcept
206     : m_erased_callable {},
207       m_invoker {}
208   {}
209
210   /* Default copy/assignment is fine.  */
211   function_view (const function_view &) = default;
212   function_view &operator= (const function_view &) = default;
213
214   /* This is the main entry point.  Use SFINAE to avoid hijacking the
215      copy constructor and to ensure that the target type is
216      compatible.  */
217   template
218     <typename Callable,
219      typename = Requires<Not<IsFunctionView<Callable>>>,
220      typename = Requires<IsCompatibleCallable<Callable>>>
221   function_view (Callable &&callable) noexcept
222   {
223     bind (callable);
224   }
225
226   /* Construct a NULL function_view.  */
227   constexpr function_view (std::nullptr_t) noexcept
228     : m_erased_callable {},
229       m_invoker {}
230   {}
231
232   /* Clear a function_view.  */
233   function_view &operator= (std::nullptr_t) noexcept
234   {
235     m_invoker = nullptr;
236     return *this;
237   }
238
239   /* Return true if the wrapper has a target, false otherwise.  Note
240      we check M_INVOKER instead of M_ERASED_CALLABLE because we don't
241      know which member of the union is active right now.  */
242   constexpr explicit operator bool () const noexcept
243   { return m_invoker != nullptr; }
244
245   /* Call the callable.  */
246   Res operator () (Args... args) const
247   { return m_invoker (m_erased_callable, std::forward<Args> (args)...); }
248
249  private:
250
251   /* Bind this function_view to a compatible function object
252      reference.  */
253   template <typename Callable>
254   void bind (Callable &callable) noexcept
255   {
256     m_erased_callable.data = (void *) std::addressof (callable);
257     m_invoker = [] (fv_detail::erased_callable ecall, Args... args)
258       noexcept (noexcept (callable (std::forward<Args> (args)...))) -> Res
259       {
260         auto &restored_callable = *static_cast<Callable *> (ecall.data);
261         /* The explicit cast to Res avoids a compile error when Res is
262            void and the callable returns non-void.  */
263         return (Res) restored_callable (std::forward<Args> (args)...);
264       };
265   }
266
267   /* Bind this function_view to a compatible function pointer.
268
269      Making this a separate function allows avoiding one indirection,
270      by storing the function pointer directly in the storage, instead
271      of a pointer to pointer.  erased_callable is then a union in
272      order to avoid storing a function pointer as a data pointer here,
273      which would be undefined.  */
274   template<class Res2, typename... Args2>
275   void bind (Res2 (*fn) (Args2...)) noexcept
276   {
277     m_erased_callable.fn = reinterpret_cast<void (*) ()> (fn);
278     m_invoker = [] (fv_detail::erased_callable ecall, Args... args)
279       noexcept (noexcept (fn (std::forward<Args> (args)...))) -> Res
280       {
281         auto restored_fn = reinterpret_cast<Res2 (*) (Args2...)> (ecall.fn);
282         /* The explicit cast to Res avoids a compile error when Res is
283            void and the callable returns non-void.  */
284         return (Res) restored_fn (std::forward<Args> (args)...);
285       };
286   }
287
288   /* Storage for the erased callable.  */
289   fv_detail::erased_callable m_erased_callable;
290
291   /* The invoker.  This is set to a capture-less lambda by one of the
292      'bind' overloads.  The lambda restores the right type of the
293      callable (which is passed as first argument), and forwards the
294      args.  */
295   Res (*m_invoker) (fv_detail::erased_callable, Args...);
296 };
297
298 /* Allow comparison with NULL.  Defer the work to the in-class
299    operator bool implementation.  */
300
301 template<typename Res, typename... Args>
302 constexpr inline bool
303 operator== (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept
304 { return !static_cast<bool> (f); }
305
306 template<typename Res, typename... Args>
307 constexpr inline bool
308 operator== (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept
309 { return !static_cast<bool> (f); }
310
311 template<typename Res, typename... Args>
312 constexpr inline bool
313 operator!= (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept
314 { return static_cast<bool> (f); }
315
316 template<typename Res, typename... Args>
317 constexpr inline bool
318 operator!= (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept
319 { return static_cast<bool> (f); }
320
321 } /* namespace gdb */
322
323 #endif