]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/common/function-view.h
Rename common to gdbsupport
[thirdparty/binutils-gdb.git] / gdb / common / function-view.h
diff --git a/gdb/common/function-view.h b/gdb/common/function-view.h
deleted file mode 100644 (file)
index 1a577ba..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-/* Copyright (C) 2017-2019 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);
-
-  You can find unit tests covering the whole API in
-  unittests/function-view-selftests.c.  */
-
-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::result_of<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 gdb */
-
-#endif