| /* Copyright (C) 2017-2024 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #ifndef COMMON_FUNCTION_VIEW_H | 
 | #define COMMON_FUNCTION_VIEW_H | 
 |  | 
 | /* function_view is a polymorphic type-erasing wrapper class that | 
 |    encapsulates a non-owning reference to arbitrary callable objects. | 
 |  | 
 |    A way to put it is that function_view is to std::function like | 
 |    std::string_view is to std::string.  While std::function stores a | 
 |    type-erased callable object internally, function_view holds a | 
 |    type-erased reference to an external callable object. | 
 |  | 
 |    This is meant to be used as callback type of a function that: | 
 |  | 
 |      #1 - Takes a callback as parameter. | 
 |  | 
 |      #2 - Wants to support arbitrary callable objects as callback type | 
 | 	  (e.g., stateful function objects, lambda closures, free | 
 | 	  functions). | 
 |  | 
 |      #3 - Does not store the callback anywhere; instead the function | 
 | 	  just calls the callback directly or forwards it to some | 
 | 	  other function that calls it. | 
 |  | 
 |      #4 - Can't be, or we don't want it to be, a template function | 
 | 	  with the callable type as template parameter.  For example, | 
 | 	  when the callback is a parameter of a virtual member | 
 | 	  function, or when putting the function template in a header | 
 | 	  would expose too much implementation detail. | 
 |  | 
 |    Note that the C-style "function pointer" + "void *data" callback | 
 |    parameter idiom fails requirement #2 above.  Please don't add new | 
 |    uses of that idiom.  I.e., something like this wouldn't work; | 
 |  | 
 |     typedef bool (iterate_over_foos_cb) (foo *f, void *user_data), | 
 |     void iterate_over_foos (iterate_over_foos_cb *callback, void *user_data); | 
 |  | 
 |     foo *find_foo_by_type (int type) | 
 |     { | 
 |       foo *found = nullptr; | 
 |  | 
 |       iterate_over_foos ([&] (foo *f, void *data) | 
 | 	{ | 
 | 	  if (foo->type == type) | 
 | 	    { | 
 | 	      found = foo; | 
 | 	      return true; // stop iterating | 
 | 	    } | 
 | 	  return false; // continue iterating | 
 | 	}, NULL); | 
 |  | 
 |       return found; | 
 |     } | 
 |  | 
 |    The above wouldn't compile, because lambdas with captures can't be | 
 |    implicitly converted to a function pointer (because a capture means | 
 |    some context data must be passed to the lambda somehow). | 
 |  | 
 |    C++11 gave us std::function as type-erased wrapper around arbitrary | 
 |    callables, however, std::function is not an ideal fit for transient | 
 |    callbacks such as the use case above.  For this use case, which is | 
 |    quite pervasive, a function_view is a better choice, because while | 
 |    function_view is light and does not require any heap allocation, | 
 |    std::function is a heavy-weight object with value semantics that | 
 |    generally requires a heap allocation on construction/assignment of | 
 |    the target callable.  In addition, while it is possible to use | 
 |    std::function in such a way that avoids most of the overhead by | 
 |    making sure to only construct it with callables of types that fit | 
 |    std::function's small object optimization, such as function | 
 |    pointers and std::reference_wrapper callables, that is quite | 
 |    inconvenient in practice, because restricting to free-function | 
 |    callables would imply no state/capture/closure, which we need in | 
 |    most cases, and std::reference_wrapper implies remembering to use | 
 |    std::ref/std::cref where the callable is constructed, with the | 
 |    added inconvenience that std::ref/std::cref have deleted rvalue-ref | 
 |    overloads, meaning you can't use unnamed/temporary lambdas with | 
 |    them. | 
 |  | 
 |    Note that because function_view is a non-owning view of a callable, | 
 |    care must be taken to ensure that the callable outlives the | 
 |    function_view that calls it.  This is not really a problem for the | 
 |    use case function_view is intended for, such as passing a temporary | 
 |    function object / lambda to a function that accepts a callback, | 
 |    because in those cases, the temporary is guaranteed to be live | 
 |    until the called function returns. | 
 |  | 
 |    Calling a function_view with no associated target is undefined, | 
 |    unlike with std::function, which throws std::bad_function_call. | 
 |    This is by design, to avoid the otherwise necessary NULL check in | 
 |    function_view::operator(). | 
 |  | 
 |    Since function_view objects are small (a pair of pointers), they | 
 |    should generally be passed around by value. | 
 |  | 
 |    Usage: | 
 |  | 
 |    Given this function that accepts a callback: | 
 |  | 
 |     void | 
 |     iterate_over_foos (gdb::function_view<void (foo *)> callback) | 
 |     { | 
 |        for (auto &foo : foos) | 
 | 	 callback (&foo); | 
 |     } | 
 |  | 
 |    you can call it like this, passing a lambda as callback: | 
 |  | 
 |     iterate_over_foos ([&] (foo *f) | 
 |       { | 
 | 	process_one_foo (f); | 
 |       }); | 
 |  | 
 |    or like this, passing a function object as callback: | 
 |  | 
 |     struct function_object | 
 |     { | 
 |       void operator() (foo *f) | 
 |       { | 
 | 	if (s->check ()) | 
 | 	  process_one_foo (f); | 
 |       } | 
 |  | 
 |       // some state | 
 |       state *s; | 
 |     }; | 
 |  | 
 |     state mystate; | 
 |     function_object matcher {&mystate}; | 
 |     iterate_over_foos (matcher); | 
 |  | 
 |   or like this, passing a function pointer as callback: | 
 |  | 
 |     iterate_over_foos (process_one_foo); | 
 |  | 
 |   There's also a gdb::make_function_view function that you can use to | 
 |   automatically create a function_view from a callable without having | 
 |   to specify the function_view's template parameter.  E.g.: | 
 |  | 
 |     auto lambda = [&] (int) { ... }; | 
 |     auto fv = gdb::make_function_view (lambda); | 
 |  | 
 |   This can be useful for example when calling a template function | 
 |   whose function_view parameter type depends on the function's | 
 |   template parameters.  In such case, you can't rely on implicit | 
 |   callable->function_view conversion for the function_view argument. | 
 |   You must pass a function_view argument already of the right type to | 
 |   the template function.  E.g., with this: | 
 |  | 
 |     template<typename T> | 
 |     void my_function (T v, gdb::function_view<void(T)> callback = nullptr); | 
 |  | 
 |   this wouldn't compile: | 
 |  | 
 |     auto lambda = [&] (int) { ... }; | 
 |     my_function (1, lambda); | 
 |  | 
 |   Note that this immediately dangles the temporary lambda object: | 
 |  | 
 |     gdb::function_view<void(int)> fv = [&] (int) { ... };  // dangles | 
 |     my_function (fv); | 
 |  | 
 |   To avoid the dangling you'd have to use a named temporary for the | 
 |   lambda: | 
 |  | 
 |     auto lambda = [&] (int) { ... }; | 
 |     gdb::function_view<void(int)> fv = lambda; | 
 |     my_function (fv); | 
 |  | 
 |   Using gdb::make_function_view instead automatically deduces the | 
 |   function_view's full type, and, avoids worrying about dangling.  For | 
 |   the example above, we could write instead: | 
 |  | 
 |     auto lambda = [&] (int) { ... }; | 
 |     my_function (1, gdb::make_function_view (lambda)); | 
 |  | 
 |   You can find unit tests covering the whole API in | 
 |   unittests/function-view-selftests.c.  */ | 
 |  | 
 | #include <type_traits> | 
 | namespace gdb { | 
 |  | 
 | namespace fv_detail { | 
 | /* Bits shared by all function_view instantiations that do not depend | 
 |    on the template parameters.  */ | 
 |  | 
 | /* Storage for the erased callable.  This is a union in order to be | 
 |    able to save both a function object (data) pointer or a function | 
 |    pointer without triggering undefined behavior.  */ | 
 | union erased_callable | 
 | { | 
 |   /* For function objects.  */ | 
 |   void *data; | 
 |  | 
 |     /* For function pointers.  */ | 
 |   void (*fn) (); | 
 | }; | 
 |  | 
 | } /* namespace fv_detail */ | 
 |  | 
 | /* Use partial specialization to get access to the callable's | 
 |    signature. */ | 
 | template<class Signature> | 
 | struct function_view; | 
 |  | 
 | template<typename Res, typename... Args> | 
 | class function_view<Res (Args...)> | 
 | { | 
 |   template<typename From, typename To> | 
 |   using CompatibleReturnType | 
 |     = Or<std::is_void<To>, | 
 | 	 std::is_same<From, To>, | 
 | 	 std::is_convertible<From, To>>; | 
 |  | 
 |   /* True if Func can be called with Args, and either the result is | 
 |      Res, convertible to Res or Res is void.  */ | 
 |   template<typename Callable, | 
 | 	   typename Res2 = typename std::invoke_result<Callable &, Args...>::type> | 
 |   struct IsCompatibleCallable : CompatibleReturnType<Res2, Res> | 
 |   {}; | 
 |  | 
 |   /* True if Callable is a function_view.  Used to avoid hijacking the | 
 |      copy ctor.  */ | 
 |   template <typename Callable> | 
 |   struct IsFunctionView | 
 |     : std::is_same<function_view, typename std::decay<Callable>::type> | 
 |   {}; | 
 |  | 
 |  public: | 
 |  | 
 |   /* NULL by default.  */ | 
 |   constexpr function_view () noexcept | 
 |     : m_erased_callable {}, | 
 |       m_invoker {} | 
 |   {} | 
 |  | 
 |   /* Default copy/assignment is fine.  */ | 
 |   function_view (const function_view &) = default; | 
 |   function_view &operator= (const function_view &) = default; | 
 |  | 
 |   /* This is the main entry point.  Use SFINAE to avoid hijacking the | 
 |      copy constructor and to ensure that the target type is | 
 |      compatible.  */ | 
 |   template | 
 |     <typename Callable, | 
 |      typename = Requires<Not<IsFunctionView<Callable>>>, | 
 |      typename = Requires<IsCompatibleCallable<Callable>>> | 
 |   function_view (Callable &&callable) noexcept | 
 |   { | 
 |     bind (callable); | 
 |   } | 
 |  | 
 |   /* Construct a NULL function_view.  */ | 
 |   constexpr function_view (std::nullptr_t) noexcept | 
 |     : m_erased_callable {}, | 
 |       m_invoker {} | 
 |   {} | 
 |  | 
 |   /* Clear a function_view.  */ | 
 |   function_view &operator= (std::nullptr_t) noexcept | 
 |   { | 
 |     m_invoker = nullptr; | 
 |     return *this; | 
 |   } | 
 |  | 
 |   /* Return true if the wrapper has a target, false otherwise.  Note | 
 |      we check M_INVOKER instead of M_ERASED_CALLABLE because we don't | 
 |      know which member of the union is active right now.  */ | 
 |   constexpr explicit operator bool () const noexcept | 
 |   { return m_invoker != nullptr; } | 
 |  | 
 |   /* Call the callable.  */ | 
 |   Res operator () (Args... args) const | 
 |   { return m_invoker (m_erased_callable, std::forward<Args> (args)...); } | 
 |  | 
 |  private: | 
 |  | 
 |   /* Bind this function_view to a compatible function object | 
 |      reference.  */ | 
 |   template <typename Callable> | 
 |   void bind (Callable &callable) noexcept | 
 |   { | 
 |     m_erased_callable.data = (void *) std::addressof (callable); | 
 |     m_invoker = [] (fv_detail::erased_callable ecall, Args... args) | 
 |       noexcept (noexcept (callable (std::forward<Args> (args)...))) -> Res | 
 |       { | 
 | 	auto &restored_callable = *static_cast<Callable *> (ecall.data); | 
 | 	/* The explicit cast to Res avoids a compile error when Res is | 
 | 	   void and the callable returns non-void.  */ | 
 | 	return (Res) restored_callable (std::forward<Args> (args)...); | 
 |       }; | 
 |   } | 
 |  | 
 |   /* Bind this function_view to a compatible function pointer. | 
 |  | 
 |      Making this a separate function allows avoiding one indirection, | 
 |      by storing the function pointer directly in the storage, instead | 
 |      of a pointer to pointer.  erased_callable is then a union in | 
 |      order to avoid storing a function pointer as a data pointer here, | 
 |      which would be undefined.  */ | 
 |   template<class Res2, typename... Args2> | 
 |   void bind (Res2 (*fn) (Args2...)) noexcept | 
 |   { | 
 |     m_erased_callable.fn = reinterpret_cast<void (*) ()> (fn); | 
 |     m_invoker = [] (fv_detail::erased_callable ecall, Args... args) | 
 |       noexcept (noexcept (fn (std::forward<Args> (args)...))) -> Res | 
 |       { | 
 | 	auto restored_fn = reinterpret_cast<Res2 (*) (Args2...)> (ecall.fn); | 
 | 	/* The explicit cast to Res avoids a compile error when Res is | 
 | 	   void and the callable returns non-void.  */ | 
 | 	return (Res) restored_fn (std::forward<Args> (args)...); | 
 |       }; | 
 |   } | 
 |  | 
 |   /* Storage for the erased callable.  */ | 
 |   fv_detail::erased_callable m_erased_callable; | 
 |  | 
 |   /* The invoker.  This is set to a capture-less lambda by one of the | 
 |      'bind' overloads.  The lambda restores the right type of the | 
 |      callable (which is passed as first argument), and forwards the | 
 |      args.  */ | 
 |   Res (*m_invoker) (fv_detail::erased_callable, Args...); | 
 | }; | 
 |  | 
 | /* Allow comparison with NULL.  Defer the work to the in-class | 
 |    operator bool implementation.  */ | 
 |  | 
 | template<typename Res, typename... Args> | 
 | constexpr inline bool | 
 | operator== (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept | 
 | { return !static_cast<bool> (f); } | 
 |  | 
 | template<typename Res, typename... Args> | 
 | constexpr inline bool | 
 | operator== (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept | 
 | { return !static_cast<bool> (f); } | 
 |  | 
 | template<typename Res, typename... Args> | 
 | constexpr inline bool | 
 | operator!= (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept | 
 | { return static_cast<bool> (f); } | 
 |  | 
 | template<typename Res, typename... Args> | 
 | constexpr inline bool | 
 | operator!= (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept | 
 | { return static_cast<bool> (f); } | 
 |  | 
 | namespace fv_detail { | 
 |  | 
 | /* Helper traits type to automatically find the right function_view | 
 |    type for a callable.  */ | 
 |  | 
 | /* Use partial specialization to get access to the callable's | 
 |    signature, for all the different callable variants.  */ | 
 |  | 
 | template<typename> | 
 | struct function_view_traits; | 
 |  | 
 | /* Main partial specialization with plain function signature type. | 
 |    All others end up redirected here.  */ | 
 | template<typename Res, typename... Args> | 
 | struct function_view_traits<Res (Args...)> | 
 | { | 
 |   using type = gdb::function_view<Res (Args...)>; | 
 | }; | 
 |  | 
 | /* Function pointers.  */ | 
 | template<typename Res, typename... Args> | 
 | struct function_view_traits<Res (*) (Args...)> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Function references.  */ | 
 | template<typename Res, typename... Args> | 
 | struct function_view_traits<Res (&) (Args...)> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Reference to function pointers.  */ | 
 | template<typename Res, typename... Args> | 
 | struct function_view_traits<Res (*&) (Args...)> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Reference to const function pointers.  */ | 
 | template<typename Res, typename... Args> | 
 | struct function_view_traits<Res (* const &) (Args...)> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Const member functions.  function_view doesn't support these, but | 
 |    we need this in order to extract the type of function objects. | 
 |    Lambdas pass here, after starting at the operator() case, | 
 |    below.  */ | 
 | template<typename Res, typename Class, typename... Args> | 
 | struct function_view_traits<Res (Class::*) (Args...) const> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Member functions.  Ditto, for function objects with non-const | 
 |    operator().  */ | 
 | template<typename Res, typename Class, typename... Args> | 
 | struct function_view_traits<Res (Class::*) (Args...)> | 
 |   : function_view_traits<Res (Args...)> | 
 | { | 
 | }; | 
 |  | 
 | /* Function objects, lambdas, std::function, any type that defines | 
 |    operator().  */ | 
 | template<typename FuncObj> | 
 | struct function_view_traits | 
 |   : function_view_traits <decltype | 
 | 			  (&std::remove_reference<FuncObj>::type::operator())> | 
 | { | 
 | }; | 
 |  | 
 | } /* namespace fv_detail */ | 
 |  | 
 | /* Make a function_view from a callable.  Useful to automatically | 
 |    deduce the function_view's template argument type.  */ | 
 | template<typename Callable> | 
 | auto make_function_view (Callable &&callable) | 
 |   -> typename fv_detail::function_view_traits<Callable>::type | 
 | { | 
 |   using fv = typename fv_detail::function_view_traits<Callable>::type; | 
 |   return fv (std::forward<Callable> (callable)); | 
 | } | 
 |  | 
 | } /* namespace gdb */ | 
 |  | 
 | #endif |