mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
Introduce gdb::make_function_view
This adds gdb::make_function_view, which lets you create a function
view from a callable without specifying the function_view's template
parameter. For example, this:
auto lambda = [&] (int) { ... };
auto fv = gdb::make_function_view (lambda);
instead of:
auto lambda = [&] (int) { ... };
gdb::function_view<void (int)> fv = lambda;
It is particularly useful if you have a template function with an
optional function_view parameter, whose type depends on the function's
template parameters. Like:
template<typename T>
void my_function (T v, gdb::function_view<void(T)> callback = nullptr);
For such a function, the type of the callback argument you pass must
already be a function_view. I.e., this wouldn't compile:
auto lambda = [&] (int) { ... };
my_function (1, lambda);
With gdb::make_function_view, you can write the call like so:
auto lambda = [&] (int) { ... };
my_function (1, gdb::make_function_view (lambda));
Unit tests included.
Tested by building with GCC 9.4, Clang 10, and GCC 4.8.5, on x86_64
GNU/Linux, and running the unit tests.
Change-Id: I5c4b3b4455ed6f0d8878cf1be189bea3ee63f626
This commit is contained in:
committed by
Tom de Vries
parent
5ee285ca3e
commit
377c3a9c91
@@ -148,6 +148,47 @@
|
||||
|
||||
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. */
|
||||
|
||||
@@ -318,6 +359,92 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user