From 14618cdd0c80a4dcdba04d8e7a651d1be8b454d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Wed, 18 Jun 2025 15:56:22 +0200 Subject: [PATCH] libcamera: base: bound_method: Move return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of copying, just move the returned value when the call is made through an argument pack. This enables, e.g. `Object::invokeMethod()` to be usable with functions returning types, such as`std::unique_ptr`, that have no copy ctor/assignment. Since there are no other users of the argument pack object, this is safe to do. Reference return types are not supported, so a simple `std::move()` is sufficient. Bug: https://bugs.libcamera.org/show_bug.cgi?id=273#c1 Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- include/libcamera/base/bound_method.h | 21 ++++++++------------- test/object-invoke.cpp | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h index 507c320d..e14614bc 100644 --- a/include/libcamera/base/bound_method.h +++ b/include/libcamera/base/bound_method.h @@ -38,11 +38,6 @@ public: { } - R returnValue() - { - return ret_; - } - std::tuple...> args_; R ret_; }; @@ -56,10 +51,6 @@ public: { } - void returnValue() - { - } - std::tuple...> args_; }; @@ -140,8 +131,10 @@ public: return func_(args...); auto pack = std::make_shared(args...); - bool sync = BoundMethodBase::activatePack(pack, deleteMethod); - return sync ? pack->returnValue() : R(); + [[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod); + + if constexpr (!std::is_void_v) + return sync ? std::move(pack->ret_) : R(); } R invoke(Args... args) override @@ -175,8 +168,10 @@ public: } auto pack = std::make_shared(args...); - bool sync = BoundMethodBase::activatePack(pack, deleteMethod); - return sync ? pack->returnValue() : R(); + [[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod); + + if constexpr (!std::is_void_v) + return sync ? std::move(pack->ret_) : R(); } R invoke(Args... args) override diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp index def1e61e..ab4a1575 100644 --- a/test/object-invoke.cpp +++ b/test/object-invoke.cpp @@ -58,6 +58,19 @@ public: return 42; } + struct MoveOnly { + MoveOnly() = default; + MoveOnly(const MoveOnly &) = delete; + MoveOnly &operator=(const MoveOnly &) = delete; + MoveOnly(MoveOnly &&) = default; + MoveOnly &operator=(MoveOnly &&) = default; + }; + + MoveOnly methodWithReturnMoveOnly() + { + return {}; + } + private: Status status_; int value_; @@ -186,6 +199,10 @@ protected: return TestFail; } + /* Test invoking a method that returns type with no copy ctor/assignment. */ + object_.invokeMethod(&InvokedObject::methodWithReturnMoveOnly, + ConnectionTypeBlocking); + return TestPass; }