From 377c3a9c91785d5df5c0d96121160e6210204cc0 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Fri, 5 Aug 2022 16:12:56 +0200 Subject: 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 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 void my_function (T v, gdb::function_view 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 --- gdb/unittests/function-view-selftests.c | 82 ++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'gdb/unittests') diff --git a/gdb/unittests/function-view-selftests.c b/gdb/unittests/function-view-selftests.c index 7af0245..726c223 100644 --- a/gdb/unittests/function-view-selftests.c +++ b/gdb/unittests/function-view-selftests.c @@ -61,7 +61,7 @@ struct plus_one_int_func_obj }; static void -run_tests () +test_function_view () { /* A simple lambda. */ auto plus_one_lambda = [] (int val) { return ++val; }; @@ -168,6 +168,86 @@ run_tests () SELF_CHECK (!check_op_eq_null); } +/* A template function where the function_view type is dependent on a + template parameter. */ + +template +static int +tmpl_func (T val, gdb::function_view callback) +{ + return callback (val) + 1; +} + +static int +make_fv_test_func (int val) +{ + return val + 1; +} + +/* A function object with const operator(). */ + +struct func_obj_const_op +{ + int operator() (int val) const + { + return val + 1; + } +}; + +/* A function object with non-const operator(). */ + +struct func_obj_non_const_op +{ + int operator() (int val) + { + return val + 1; + } +}; + +static void +test_make_function_view () +{ + /* Function reference. */ + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (make_fv_test_func))); + + /* Function pointer. */ + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (&make_fv_test_func))); + + /* Reference to const and non-const function pointers. */ + typedef int (*func_ptr) (int); + func_ptr ptr = make_fv_test_func; + const func_ptr cptr = make_fv_test_func; + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (ptr))); + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (cptr))); + + /* Lambdas. */ + + auto lambda = [] (int val) -> int { return val + 1; }; + + /* This wouldn't compile, since tmpl_func is a template and its + function_view argument's callable type is a dependent type. The + passed argument must be of the exact type of the function's + parameter. */ + // SELF_CHECK (3 == tmpl_func (1, lambda)); + + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (lambda))); + + /* Regular function objects. */ + + func_obj_non_const_op fobj; + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (fobj))); + + func_obj_const_op cfobj; + SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (cfobj))); +} + +static void +run_tests () +{ + test_function_view (); + test_make_function_view (); +} + } /* namespace function_view */ } /* namespace selftests */ -- cgit v1.1