xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/function-view.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1*6881a400Schristos /* Copyright (C) 2017-2023 Free Software Foundation, Inc.
27d62b00eSchristos 
37d62b00eSchristos    This file is part of GDB.
47d62b00eSchristos 
57d62b00eSchristos    This program is free software; you can redistribute it and/or modify
67d62b00eSchristos    it under the terms of the GNU General Public License as published by
77d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
87d62b00eSchristos    (at your option) any later version.
97d62b00eSchristos 
107d62b00eSchristos    This program is distributed in the hope that it will be useful,
117d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
127d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137d62b00eSchristos    GNU General Public License for more details.
147d62b00eSchristos 
157d62b00eSchristos    You should have received a copy of the GNU General Public License
167d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
177d62b00eSchristos 
187d62b00eSchristos #ifndef COMMON_FUNCTION_VIEW_H
197d62b00eSchristos #define COMMON_FUNCTION_VIEW_H
207d62b00eSchristos 
217d62b00eSchristos /* function_view is a polymorphic type-erasing wrapper class that
227d62b00eSchristos    encapsulates a non-owning reference to arbitrary callable objects.
237d62b00eSchristos 
247d62b00eSchristos    A way to put it is that function_view is to std::function like
257d62b00eSchristos    std::string_view is to std::string.  While std::function stores a
267d62b00eSchristos    type-erased callable object internally, function_view holds a
277d62b00eSchristos    type-erased reference to an external callable object.
287d62b00eSchristos 
297d62b00eSchristos    This is meant to be used as callback type of a function that:
307d62b00eSchristos 
317d62b00eSchristos      #1 - Takes a callback as parameter.
327d62b00eSchristos 
337d62b00eSchristos      #2 - Wants to support arbitrary callable objects as callback type
347d62b00eSchristos 	  (e.g., stateful function objects, lambda closures, free
357d62b00eSchristos 	  functions).
367d62b00eSchristos 
377d62b00eSchristos      #3 - Does not store the callback anywhere; instead the function
387d62b00eSchristos 	  just calls the callback directly or forwards it to some
397d62b00eSchristos 	  other function that calls it.
407d62b00eSchristos 
417d62b00eSchristos      #4 - Can't be, or we don't want it to be, a template function
427d62b00eSchristos 	  with the callable type as template parameter.  For example,
437d62b00eSchristos 	  when the callback is a parameter of a virtual member
447d62b00eSchristos 	  function, or when putting the function template in a header
457d62b00eSchristos 	  would expose too much implementation detail.
467d62b00eSchristos 
477d62b00eSchristos    Note that the C-style "function pointer" + "void *data" callback
487d62b00eSchristos    parameter idiom fails requirement #2 above.  Please don't add new
497d62b00eSchristos    uses of that idiom.  I.e., something like this wouldn't work;
507d62b00eSchristos 
517d62b00eSchristos     typedef bool (iterate_over_foos_cb) (foo *f, void *user_data),
527d62b00eSchristos     void iterate_over_foos (iterate_over_foos_cb *callback, void *user_data);
537d62b00eSchristos 
547d62b00eSchristos     foo *find_foo_by_type (int type)
557d62b00eSchristos     {
567d62b00eSchristos       foo *found = nullptr;
577d62b00eSchristos 
587d62b00eSchristos       iterate_over_foos ([&] (foo *f, void *data)
597d62b00eSchristos 	{
607d62b00eSchristos 	  if (foo->type == type)
617d62b00eSchristos 	    {
627d62b00eSchristos 	      found = foo;
637d62b00eSchristos 	      return true; // stop iterating
647d62b00eSchristos 	    }
657d62b00eSchristos 	  return false; // continue iterating
667d62b00eSchristos 	}, NULL);
677d62b00eSchristos 
687d62b00eSchristos       return found;
697d62b00eSchristos     }
707d62b00eSchristos 
717d62b00eSchristos    The above wouldn't compile, because lambdas with captures can't be
727d62b00eSchristos    implicitly converted to a function pointer (because a capture means
737d62b00eSchristos    some context data must be passed to the lambda somehow).
747d62b00eSchristos 
757d62b00eSchristos    C++11 gave us std::function as type-erased wrapper around arbitrary
767d62b00eSchristos    callables, however, std::function is not an ideal fit for transient
777d62b00eSchristos    callbacks such as the use case above.  For this use case, which is
787d62b00eSchristos    quite pervasive, a function_view is a better choice, because while
797d62b00eSchristos    function_view is light and does not require any heap allocation,
807d62b00eSchristos    std::function is a heavy-weight object with value semantics that
817d62b00eSchristos    generally requires a heap allocation on construction/assignment of
827d62b00eSchristos    the target callable.  In addition, while it is possible to use
837d62b00eSchristos    std::function in such a way that avoids most of the overhead by
847d62b00eSchristos    making sure to only construct it with callables of types that fit
857d62b00eSchristos    std::function's small object optimization, such as function
867d62b00eSchristos    pointers and std::reference_wrapper callables, that is quite
877d62b00eSchristos    inconvenient in practice, because restricting to free-function
887d62b00eSchristos    callables would imply no state/capture/closure, which we need in
897d62b00eSchristos    most cases, and std::reference_wrapper implies remembering to use
907d62b00eSchristos    std::ref/std::cref where the callable is constructed, with the
917d62b00eSchristos    added inconvenience that std::ref/std::cref have deleted rvalue-ref
927d62b00eSchristos    overloads, meaning you can't use unnamed/temporary lambdas with
937d62b00eSchristos    them.
947d62b00eSchristos 
957d62b00eSchristos    Note that because function_view is a non-owning view of a callable,
967d62b00eSchristos    care must be taken to ensure that the callable outlives the
977d62b00eSchristos    function_view that calls it.  This is not really a problem for the
987d62b00eSchristos    use case function_view is intended for, such as passing a temporary
997d62b00eSchristos    function object / lambda to a function that accepts a callback,
1007d62b00eSchristos    because in those cases, the temporary is guaranteed to be live
1017d62b00eSchristos    until the called function returns.
1027d62b00eSchristos 
1037d62b00eSchristos    Calling a function_view with no associated target is undefined,
1047d62b00eSchristos    unlike with std::function, which throws std::bad_function_call.
1057d62b00eSchristos    This is by design, to avoid the otherwise necessary NULL check in
1067d62b00eSchristos    function_view::operator().
1077d62b00eSchristos 
1087d62b00eSchristos    Since function_view objects are small (a pair of pointers), they
1097d62b00eSchristos    should generally be passed around by value.
1107d62b00eSchristos 
1117d62b00eSchristos    Usage:
1127d62b00eSchristos 
1137d62b00eSchristos    Given this function that accepts a callback:
1147d62b00eSchristos 
1157d62b00eSchristos     void
1167d62b00eSchristos     iterate_over_foos (gdb::function_view<void (foo *)> callback)
1177d62b00eSchristos     {
1187d62b00eSchristos        for (auto &foo : foos)
1197d62b00eSchristos 	 callback (&foo);
1207d62b00eSchristos     }
1217d62b00eSchristos 
1227d62b00eSchristos    you can call it like this, passing a lambda as callback:
1237d62b00eSchristos 
1247d62b00eSchristos     iterate_over_foos ([&] (foo *f)
1257d62b00eSchristos       {
1267d62b00eSchristos 	process_one_foo (f);
1277d62b00eSchristos       });
1287d62b00eSchristos 
1297d62b00eSchristos    or like this, passing a function object as callback:
1307d62b00eSchristos 
1317d62b00eSchristos     struct function_object
1327d62b00eSchristos     {
1337d62b00eSchristos       void operator() (foo *f)
1347d62b00eSchristos       {
1357d62b00eSchristos 	if (s->check ())
1367d62b00eSchristos 	  process_one_foo (f);
1377d62b00eSchristos       }
1387d62b00eSchristos 
1397d62b00eSchristos       // some state
1407d62b00eSchristos       state *s;
1417d62b00eSchristos     };
1427d62b00eSchristos 
1437d62b00eSchristos     state mystate;
1447d62b00eSchristos     function_object matcher {&mystate};
1457d62b00eSchristos     iterate_over_foos (matcher);
1467d62b00eSchristos 
1477d62b00eSchristos   or like this, passing a function pointer as callback:
1487d62b00eSchristos 
1497d62b00eSchristos     iterate_over_foos (process_one_foo);
1507d62b00eSchristos 
151*6881a400Schristos   There's also a gdb::make_function_view function that you can use to
152*6881a400Schristos   automatically create a function_view from a callable without having
153*6881a400Schristos   to specify the function_view's template parameter.  E.g.:
154*6881a400Schristos 
155*6881a400Schristos     auto lambda = [&] (int) { ... };
156*6881a400Schristos     auto fv = gdb::make_function_view (lambda);
157*6881a400Schristos 
158*6881a400Schristos   This can be useful for example when calling a template function
159*6881a400Schristos   whose function_view parameter type depends on the function's
160*6881a400Schristos   template parameters.  In such case, you can't rely on implicit
161*6881a400Schristos   callable->function_view conversion for the function_view argument.
162*6881a400Schristos   You must pass a function_view argument already of the right type to
163*6881a400Schristos   the template function.  E.g., with this:
164*6881a400Schristos 
165*6881a400Schristos     template<typename T>
166*6881a400Schristos     void my_function (T v, gdb::function_view<void(T)> callback = nullptr);
167*6881a400Schristos 
168*6881a400Schristos   this wouldn't compile:
169*6881a400Schristos 
170*6881a400Schristos     auto lambda = [&] (int) { ... };
171*6881a400Schristos     my_function (1, lambda);
172*6881a400Schristos 
173*6881a400Schristos   Note that this immediately dangles the temporary lambda object:
174*6881a400Schristos 
175*6881a400Schristos     gdb::function_view<void(int)> fv = [&] (int) { ... };  // dangles
176*6881a400Schristos     my_function (fv);
177*6881a400Schristos 
178*6881a400Schristos   To avoid the dangling you'd have to use a named temporary for the
179*6881a400Schristos   lambda:
180*6881a400Schristos 
181*6881a400Schristos     auto lambda = [&] (int) { ... };
182*6881a400Schristos     gdb::function_view<void(int)> fv = lambda;
183*6881a400Schristos     my_function (fv);
184*6881a400Schristos 
185*6881a400Schristos   Using gdb::make_function_view instead automatically deduces the
186*6881a400Schristos   function_view's full type, and, avoids worrying about dangling.  For
187*6881a400Schristos   the example above, we could write instead:
188*6881a400Schristos 
189*6881a400Schristos     auto lambda = [&] (int) { ... };
190*6881a400Schristos     my_function (1, gdb::make_function_view (lambda));
191*6881a400Schristos 
1927d62b00eSchristos   You can find unit tests covering the whole API in
1937d62b00eSchristos   unittests/function-view-selftests.c.  */
1947d62b00eSchristos 
195*6881a400Schristos #include "invoke-result.h"
1967d62b00eSchristos namespace gdb {
1977d62b00eSchristos 
1987d62b00eSchristos namespace fv_detail {
1997d62b00eSchristos /* Bits shared by all function_view instantiations that do not depend
2007d62b00eSchristos    on the template parameters.  */
2017d62b00eSchristos 
2027d62b00eSchristos /* Storage for the erased callable.  This is a union in order to be
2037d62b00eSchristos    able to save both a function object (data) pointer or a function
2047d62b00eSchristos    pointer without triggering undefined behavior.  */
2057d62b00eSchristos union erased_callable
2067d62b00eSchristos {
2077d62b00eSchristos   /* For function objects.  */
2087d62b00eSchristos   void *data;
2097d62b00eSchristos 
2107d62b00eSchristos     /* For function pointers.  */
2117d62b00eSchristos   void (*fn) ();
2127d62b00eSchristos };
2137d62b00eSchristos 
2147d62b00eSchristos } /* namespace fv_detail */
2157d62b00eSchristos 
2167d62b00eSchristos /* Use partial specialization to get access to the callable's
2177d62b00eSchristos    signature. */
2187d62b00eSchristos template<class Signature>
2197d62b00eSchristos struct function_view;
2207d62b00eSchristos 
2217d62b00eSchristos template<typename Res, typename... Args>
2227d62b00eSchristos class function_view<Res (Args...)>
2237d62b00eSchristos {
2247d62b00eSchristos   template<typename From, typename To>
2257d62b00eSchristos   using CompatibleReturnType
2267d62b00eSchristos     = Or<std::is_void<To>,
2277d62b00eSchristos 	 std::is_same<From, To>,
2287d62b00eSchristos 	 std::is_convertible<From, To>>;
2297d62b00eSchristos 
2307d62b00eSchristos   /* True if Func can be called with Args, and either the result is
2317d62b00eSchristos      Res, convertible to Res or Res is void.  */
2327d62b00eSchristos   template<typename Callable,
233*6881a400Schristos 	   typename Res2 = typename gdb::invoke_result<Callable &, Args...>::type>
2347d62b00eSchristos   struct IsCompatibleCallable : CompatibleReturnType<Res2, Res>
2357d62b00eSchristos   {};
2367d62b00eSchristos 
2377d62b00eSchristos   /* True if Callable is a function_view.  Used to avoid hijacking the
2387d62b00eSchristos      copy ctor.  */
2397d62b00eSchristos   template <typename Callable>
2407d62b00eSchristos   struct IsFunctionView
2417d62b00eSchristos     : std::is_same<function_view, typename std::decay<Callable>::type>
2427d62b00eSchristos   {};
2437d62b00eSchristos 
2447d62b00eSchristos  public:
2457d62b00eSchristos 
2467d62b00eSchristos   /* NULL by default.  */
2477d62b00eSchristos   constexpr function_view () noexcept
2487d62b00eSchristos     : m_erased_callable {},
2497d62b00eSchristos       m_invoker {}
2507d62b00eSchristos   {}
2517d62b00eSchristos 
2527d62b00eSchristos   /* Default copy/assignment is fine.  */
2537d62b00eSchristos   function_view (const function_view &) = default;
2547d62b00eSchristos   function_view &operator= (const function_view &) = default;
2557d62b00eSchristos 
2567d62b00eSchristos   /* This is the main entry point.  Use SFINAE to avoid hijacking the
2577d62b00eSchristos      copy constructor and to ensure that the target type is
2587d62b00eSchristos      compatible.  */
2597d62b00eSchristos   template
2607d62b00eSchristos     <typename Callable,
2617d62b00eSchristos      typename = Requires<Not<IsFunctionView<Callable>>>,
2627d62b00eSchristos      typename = Requires<IsCompatibleCallable<Callable>>>
2637d62b00eSchristos   function_view (Callable &&callable) noexcept
2647d62b00eSchristos   {
2657d62b00eSchristos     bind (callable);
2667d62b00eSchristos   }
2677d62b00eSchristos 
2687d62b00eSchristos   /* Construct a NULL function_view.  */
2697d62b00eSchristos   constexpr function_view (std::nullptr_t) noexcept
2707d62b00eSchristos     : m_erased_callable {},
2717d62b00eSchristos       m_invoker {}
2727d62b00eSchristos   {}
2737d62b00eSchristos 
2747d62b00eSchristos   /* Clear a function_view.  */
2757d62b00eSchristos   function_view &operator= (std::nullptr_t) noexcept
2767d62b00eSchristos   {
2777d62b00eSchristos     m_invoker = nullptr;
2787d62b00eSchristos     return *this;
2797d62b00eSchristos   }
2807d62b00eSchristos 
2817d62b00eSchristos   /* Return true if the wrapper has a target, false otherwise.  Note
2827d62b00eSchristos      we check M_INVOKER instead of M_ERASED_CALLABLE because we don't
2837d62b00eSchristos      know which member of the union is active right now.  */
2847d62b00eSchristos   constexpr explicit operator bool () const noexcept
2857d62b00eSchristos   { return m_invoker != nullptr; }
2867d62b00eSchristos 
2877d62b00eSchristos   /* Call the callable.  */
2887d62b00eSchristos   Res operator () (Args... args) const
2897d62b00eSchristos   { return m_invoker (m_erased_callable, std::forward<Args> (args)...); }
2907d62b00eSchristos 
2917d62b00eSchristos  private:
2927d62b00eSchristos 
2937d62b00eSchristos   /* Bind this function_view to a compatible function object
2947d62b00eSchristos      reference.  */
2957d62b00eSchristos   template <typename Callable>
2967d62b00eSchristos   void bind (Callable &callable) noexcept
2977d62b00eSchristos   {
2987d62b00eSchristos     m_erased_callable.data = (void *) std::addressof (callable);
2997d62b00eSchristos     m_invoker = [] (fv_detail::erased_callable ecall, Args... args)
3007d62b00eSchristos       noexcept (noexcept (callable (std::forward<Args> (args)...))) -> Res
3017d62b00eSchristos       {
3027d62b00eSchristos 	auto &restored_callable = *static_cast<Callable *> (ecall.data);
3037d62b00eSchristos 	/* The explicit cast to Res avoids a compile error when Res is
3047d62b00eSchristos 	   void and the callable returns non-void.  */
3057d62b00eSchristos 	return (Res) restored_callable (std::forward<Args> (args)...);
3067d62b00eSchristos       };
3077d62b00eSchristos   }
3087d62b00eSchristos 
3097d62b00eSchristos   /* Bind this function_view to a compatible function pointer.
3107d62b00eSchristos 
3117d62b00eSchristos      Making this a separate function allows avoiding one indirection,
3127d62b00eSchristos      by storing the function pointer directly in the storage, instead
3137d62b00eSchristos      of a pointer to pointer.  erased_callable is then a union in
3147d62b00eSchristos      order to avoid storing a function pointer as a data pointer here,
3157d62b00eSchristos      which would be undefined.  */
3167d62b00eSchristos   template<class Res2, typename... Args2>
3177d62b00eSchristos   void bind (Res2 (*fn) (Args2...)) noexcept
3187d62b00eSchristos   {
3197d62b00eSchristos     m_erased_callable.fn = reinterpret_cast<void (*) ()> (fn);
3207d62b00eSchristos     m_invoker = [] (fv_detail::erased_callable ecall, Args... args)
3217d62b00eSchristos       noexcept (noexcept (fn (std::forward<Args> (args)...))) -> Res
3227d62b00eSchristos       {
3237d62b00eSchristos 	auto restored_fn = reinterpret_cast<Res2 (*) (Args2...)> (ecall.fn);
3247d62b00eSchristos 	/* The explicit cast to Res avoids a compile error when Res is
3257d62b00eSchristos 	   void and the callable returns non-void.  */
3267d62b00eSchristos 	return (Res) restored_fn (std::forward<Args> (args)...);
3277d62b00eSchristos       };
3287d62b00eSchristos   }
3297d62b00eSchristos 
3307d62b00eSchristos   /* Storage for the erased callable.  */
3317d62b00eSchristos   fv_detail::erased_callable m_erased_callable;
3327d62b00eSchristos 
3337d62b00eSchristos   /* The invoker.  This is set to a capture-less lambda by one of the
3347d62b00eSchristos      'bind' overloads.  The lambda restores the right type of the
3357d62b00eSchristos      callable (which is passed as first argument), and forwards the
3367d62b00eSchristos      args.  */
3377d62b00eSchristos   Res (*m_invoker) (fv_detail::erased_callable, Args...);
3387d62b00eSchristos };
3397d62b00eSchristos 
3407d62b00eSchristos /* Allow comparison with NULL.  Defer the work to the in-class
3417d62b00eSchristos    operator bool implementation.  */
3427d62b00eSchristos 
3437d62b00eSchristos template<typename Res, typename... Args>
3447d62b00eSchristos constexpr inline bool
3457d62b00eSchristos operator== (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept
3467d62b00eSchristos { return !static_cast<bool> (f); }
3477d62b00eSchristos 
3487d62b00eSchristos template<typename Res, typename... Args>
3497d62b00eSchristos constexpr inline bool
3507d62b00eSchristos operator== (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept
3517d62b00eSchristos { return !static_cast<bool> (f); }
3527d62b00eSchristos 
3537d62b00eSchristos template<typename Res, typename... Args>
3547d62b00eSchristos constexpr inline bool
3557d62b00eSchristos operator!= (const function_view<Res (Args...)> &f, std::nullptr_t) noexcept
3567d62b00eSchristos { return static_cast<bool> (f); }
3577d62b00eSchristos 
3587d62b00eSchristos template<typename Res, typename... Args>
3597d62b00eSchristos constexpr inline bool
3607d62b00eSchristos operator!= (std::nullptr_t, const function_view<Res (Args...)> &f) noexcept
3617d62b00eSchristos { return static_cast<bool> (f); }
3627d62b00eSchristos 
363*6881a400Schristos namespace fv_detail {
364*6881a400Schristos 
365*6881a400Schristos /* Helper traits type to automatically find the right function_view
366*6881a400Schristos    type for a callable.  */
367*6881a400Schristos 
368*6881a400Schristos /* Use partial specialization to get access to the callable's
369*6881a400Schristos    signature, for all the different callable variants.  */
370*6881a400Schristos 
371*6881a400Schristos template<typename>
372*6881a400Schristos struct function_view_traits;
373*6881a400Schristos 
374*6881a400Schristos /* Main partial specialization with plain function signature type.
375*6881a400Schristos    All others end up redirected here.  */
376*6881a400Schristos template<typename Res, typename... Args>
377*6881a400Schristos struct function_view_traits<Res (Args...)>
378*6881a400Schristos {
379*6881a400Schristos   using type = gdb::function_view<Res (Args...)>;
380*6881a400Schristos };
381*6881a400Schristos 
382*6881a400Schristos /* Function pointers.  */
383*6881a400Schristos template<typename Res, typename... Args>
384*6881a400Schristos struct function_view_traits<Res (*) (Args...)>
385*6881a400Schristos   : function_view_traits<Res (Args...)>
386*6881a400Schristos {
387*6881a400Schristos };
388*6881a400Schristos 
389*6881a400Schristos /* Function references.  */
390*6881a400Schristos template<typename Res, typename... Args>
391*6881a400Schristos struct function_view_traits<Res (&) (Args...)>
392*6881a400Schristos   : function_view_traits<Res (Args...)>
393*6881a400Schristos {
394*6881a400Schristos };
395*6881a400Schristos 
396*6881a400Schristos /* Reference to function pointers.  */
397*6881a400Schristos template<typename Res, typename... Args>
398*6881a400Schristos struct function_view_traits<Res (*&) (Args...)>
399*6881a400Schristos   : function_view_traits<Res (Args...)>
400*6881a400Schristos {
401*6881a400Schristos };
402*6881a400Schristos 
403*6881a400Schristos /* Reference to const function pointers.  */
404*6881a400Schristos template<typename Res, typename... Args>
405*6881a400Schristos struct function_view_traits<Res (* const &) (Args...)>
406*6881a400Schristos   : function_view_traits<Res (Args...)>
407*6881a400Schristos {
408*6881a400Schristos };
409*6881a400Schristos 
410*6881a400Schristos /* Const member functions.  function_view doesn't support these, but
411*6881a400Schristos    we need this in order to extract the type of function objects.
412*6881a400Schristos    Lambdas pass here, after starting at the operator() case,
413*6881a400Schristos    below.  */
414*6881a400Schristos template<typename Res, typename Class, typename... Args>
415*6881a400Schristos struct function_view_traits<Res (Class::*) (Args...) const>
416*6881a400Schristos   : function_view_traits<Res (Args...)>
417*6881a400Schristos {
418*6881a400Schristos };
419*6881a400Schristos 
420*6881a400Schristos /* Member functions.  Ditto, for function objects with non-const
421*6881a400Schristos    operator().  */
422*6881a400Schristos template<typename Res, typename Class, typename... Args>
423*6881a400Schristos struct function_view_traits<Res (Class::*) (Args...)>
424*6881a400Schristos   : function_view_traits<Res (Args...)>
425*6881a400Schristos {
426*6881a400Schristos };
427*6881a400Schristos 
428*6881a400Schristos /* Function objects, lambdas, std::function, any type that defines
429*6881a400Schristos    operator().  */
430*6881a400Schristos template<typename FuncObj>
431*6881a400Schristos struct function_view_traits
432*6881a400Schristos   : function_view_traits <decltype
433*6881a400Schristos 			  (&std::remove_reference<FuncObj>::type::operator())>
434*6881a400Schristos {
435*6881a400Schristos };
436*6881a400Schristos 
437*6881a400Schristos } /* namespace fv_detail */
438*6881a400Schristos 
439*6881a400Schristos /* Make a function_view from a callable.  Useful to automatically
440*6881a400Schristos    deduce the function_view's template argument type.  */
441*6881a400Schristos template<typename Callable>
442*6881a400Schristos auto make_function_view (Callable &&callable)
443*6881a400Schristos   -> typename fv_detail::function_view_traits<Callable>::type
444*6881a400Schristos {
445*6881a400Schristos   using fv = typename fv_detail::function_view_traits<Callable>::type;
446*6881a400Schristos   return fv (std::forward<Callable> (callable));
447*6881a400Schristos }
448*6881a400Schristos 
4497d62b00eSchristos } /* namespace gdb */
4507d62b00eSchristos 
4517d62b00eSchristos #endif
452