cpp-common/bt2c: add bt2c::call()
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 23 Nov 2023 05:46:16 +0000 (00:46 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 14 Dec 2023 15:57:04 +0000 (10:57 -0500)
This new function partially implements INVOKE.

It's bt2c::call() instead of bt2s::invoke() because it's not a perfect
drop-in replacement (not forwarding `func` because
`std::reference_wrapper` requires that the parameter isn't an rvalue).

The std::ref() trick is taken from [1].

My main use case for this is IIFE (initializing some `const` variable
from a parameter-less lambda call) without risking to forget the
trailing `()` to actually call it:

    const auto meow = [&aqua, &fina] {
        // some steps
        return mix;
    }; // oops, forgot `()` here

Instead:

    const auto meow = bt2c::call([&aqua, &fina] {
        // some steps
        return mix;
    });

When you see bt2c::call(), you know there's a call.

You can also use bt2c::call() for most use cases [2] of std::invoke()
(C++17), for example:

    template <typename MethT, typename ObjT>
    void f(MethT&& meth, ObjT&& obj, const int val)
    {
        bt2c::call(std::forward<MethT>(meth), std::forward<ObjT>(obj), val, 42);
    }

    struct Meow
    {
        void mix(const int a, const int b)
        {
            std::cout << a << ":" << b << std::endl;
        }
    };

    int main()
    {
        Meow meow;

        f(&Meow::mix, meow, 17);
    }

[1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0312r1.html
[2]: https://devblogs.microsoft.com/oldnewthing/20220401-00/?p=106426

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Ib7db0315ee6f68f168793488a7da67c1bc410fb8
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11425
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
CI-Build: Simon Marchi <simon.marchi@efficios.com>
Tested-by: jenkins <jenkins@lttng.org>
src/Makefile.am
src/cpp-common/bt2c/call.hpp [new file with mode: 0644]

index 2166e36d00358d3342aaddc1599def1f912a45be..4c6126b2cca60464cc9453519043710702cc11cd 100644 (file)
@@ -43,6 +43,7 @@ noinst_HEADERS = \
        cpp-common/bt2/value.hpp \
        cpp-common/bt2/wrap.hpp \
        cpp-common/bt2c/align.hpp \
+       cpp-common/bt2c/call.hpp \
        cpp-common/bt2c/endian.hpp \
        cpp-common/bt2c/exc.hpp \
        cpp-common/bt2c/glib-up.hpp \
diff --git a/src/cpp-common/bt2c/call.hpp b/src/cpp-common/bt2c/call.hpp
new file mode 100644 (file)
index 0000000..3241f73
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef BABELTRACE_CPP_COMMON_BT2C_CALL_HPP
+#define BABELTRACE_CPP_COMMON_BT2C_CALL_HPP
+
+#include <functional>
+#include <utility>
+
+namespace bt2c {
+
+/*
+ * Partial implementation of INVOKE.
+ *
+ * As found in
+ * <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0312r1.html>.
+ */
+template <typename FuncT, typename... ArgTs>
+auto call(FuncT func, ArgTs&&...args) -> decltype(std::ref(func)(std::forward<ArgTs>(args)...))
+{
+    return std::ref(func)(std::forward<ArgTs>(args)...);
+}
+
+} /* namespace bt2c */
+
+#endif /* BABELTRACE_CPP_COMMON_BT2C_CALL_HPP */
This page took 0.026468 seconds and 4 git commands to generate.