libcamera: base: bound_method: Move return value
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 <barnabas.pocze@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
@@ -38,11 +38,6 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
R returnValue()
|
|
||||||
{
|
|
||||||
return ret_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<typename std::remove_reference_t<Args>...> args_;
|
std::tuple<typename std::remove_reference_t<Args>...> args_;
|
||||||
R ret_;
|
R ret_;
|
||||||
};
|
};
|
||||||
@@ -56,10 +51,6 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void returnValue()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<typename std::remove_reference_t<Args>...> args_;
|
std::tuple<typename std::remove_reference_t<Args>...> args_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,8 +131,10 @@ public:
|
|||||||
return func_(args...);
|
return func_(args...);
|
||||||
|
|
||||||
auto pack = std::make_shared<PackType>(args...);
|
auto pack = std::make_shared<PackType>(args...);
|
||||||
bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
|
[[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
|
||||||
return sync ? pack->returnValue() : R();
|
|
||||||
|
if constexpr (!std::is_void_v<R>)
|
||||||
|
return sync ? std::move(pack->ret_) : R();
|
||||||
}
|
}
|
||||||
|
|
||||||
R invoke(Args... args) override
|
R invoke(Args... args) override
|
||||||
@@ -175,8 +168,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto pack = std::make_shared<PackType>(args...);
|
auto pack = std::make_shared<PackType>(args...);
|
||||||
bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
|
[[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
|
||||||
return sync ? pack->returnValue() : R();
|
|
||||||
|
if constexpr (!std::is_void_v<R>)
|
||||||
|
return sync ? std::move(pack->ret_) : R();
|
||||||
}
|
}
|
||||||
|
|
||||||
R invoke(Args... args) override
|
R invoke(Args... args) override
|
||||||
|
|||||||
@@ -58,6 +58,19 @@ public:
|
|||||||
return 42;
|
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:
|
private:
|
||||||
Status status_;
|
Status status_;
|
||||||
int value_;
|
int value_;
|
||||||
@@ -186,6 +199,10 @@ protected:
|
|||||||
return TestFail;
|
return TestFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test invoking a method that returns type with no copy ctor/assignment. */
|
||||||
|
object_.invokeMethod(&InvokedObject::methodWithReturnMoveOnly,
|
||||||
|
ConnectionTypeBlocking);
|
||||||
|
|
||||||
return TestPass;
|
return TestPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user