libcamera: bound_method: Support bindings to non-void methods
The bound method implementation is restricted to binding to void methods as return values are not supported. This complicates usage of bound methods, as non-void methods used a slots or Object::invokeMethod() targets need to be wrapped in a void method. Simplify this by supporting arbitrary return types and ignoring the return value. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
@@ -79,7 +79,7 @@ public:
|
||||
std::tuple<typename std::remove_reference<Args>::type...> args_;
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
template<typename R, typename... Args>
|
||||
class BoundMethodArgs : public BoundMethodBase
|
||||
{
|
||||
public:
|
||||
@@ -107,19 +107,19 @@ public:
|
||||
virtual void invoke(Args... args) = 0;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
class BoundMemberMethod : public BoundMethodArgs<Args...>
|
||||
template<typename T, typename R, typename... Args>
|
||||
class BoundMemberMethod : public BoundMethodArgs<R, Args...>
|
||||
{
|
||||
public:
|
||||
using PackType = typename BoundMethodArgs<Args...>::PackType;
|
||||
using PackType = typename BoundMethodArgs<R, Args...>::PackType;
|
||||
|
||||
BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...),
|
||||
BoundMemberMethod(T *obj, Object *object, R (T::*func)(Args...),
|
||||
ConnectionType type = ConnectionTypeAuto)
|
||||
: BoundMethodArgs<Args...>(obj, object, type), func_(func)
|
||||
: BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool match(void (T::*func)(Args...)) const { return func == func_; }
|
||||
bool match(R (T::*func)(Args...)) const { return func == func_; }
|
||||
|
||||
void activate(Args... args, bool deleteMethod = false) override
|
||||
{
|
||||
@@ -135,20 +135,20 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void (T::*func_)(Args...);
|
||||
R (T::*func_)(Args...);
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class BoundStaticMethod : public BoundMethodArgs<Args...>
|
||||
template<typename R, typename... Args>
|
||||
class BoundStaticMethod : public BoundMethodArgs<R, Args...>
|
||||
{
|
||||
public:
|
||||
BoundStaticMethod(void (*func)(Args...))
|
||||
: BoundMethodArgs<Args...>(nullptr, nullptr, ConnectionTypeAuto),
|
||||
BoundStaticMethod(R (*func)(Args...))
|
||||
: BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),
|
||||
func_(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool match(void (*func)(Args...)) const { return func == func_; }
|
||||
bool match(R (*func)(Args...)) const { return func == func_; }
|
||||
|
||||
void activate(Args... args, bool deleteMethod = false) override
|
||||
{
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
void invoke(Args...) override {}
|
||||
|
||||
private:
|
||||
void (*func_)(Args...);
|
||||
R (*func_)(Args...);
|
||||
};
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
||||
@@ -29,13 +29,13 @@ public:
|
||||
|
||||
void postMessage(std::unique_ptr<Message> msg);
|
||||
|
||||
template<typename T, typename... FuncArgs, typename... Args,
|
||||
template<typename T, typename R, typename... FuncArgs, typename... Args,
|
||||
typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
|
||||
void invokeMethod(void (T::*func)(FuncArgs...), ConnectionType type,
|
||||
void invokeMethod(R (T::*func)(FuncArgs...), ConnectionType type,
|
||||
Args... args)
|
||||
{
|
||||
T *obj = static_cast<T *>(this);
|
||||
auto *method = new BoundMemberMethod<T, FuncArgs...>(obj, this, func, type);
|
||||
auto *method = new BoundMemberMethod<T, R, FuncArgs...>(obj, this, func, type);
|
||||
method->activate(args..., true);
|
||||
}
|
||||
|
||||
|
||||
+20
-17
@@ -54,27 +54,28 @@ public:
|
||||
}
|
||||
|
||||
#ifndef __DOXYGEN__
|
||||
template<typename T, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
|
||||
void connect(T *obj, void (T::*func)(Args...),
|
||||
template<typename T, typename R, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
|
||||
void connect(T *obj, R (T::*func)(Args...),
|
||||
ConnectionType type = ConnectionTypeAuto)
|
||||
{
|
||||
Object *object = static_cast<Object *>(obj);
|
||||
object->connect(this);
|
||||
slots_.push_back(new BoundMemberMethod<T, Args...>(obj, object, func, type));
|
||||
slots_.push_back(new BoundMemberMethod<T, void, Args...>(obj, object, func, type));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Object, T>::value>::type * = nullptr>
|
||||
template<typename T, typename R, typename std::enable_if<!std::is_base_of<Object, T>::value>::type * = nullptr>
|
||||
#else
|
||||
template<typename T>
|
||||
template<typename T, typename R>
|
||||
#endif
|
||||
void connect(T *obj, void (T::*func)(Args...))
|
||||
void connect(T *obj, R (T::*func)(Args...))
|
||||
{
|
||||
slots_.push_back(new BoundMemberMethod<T, Args...>(obj, nullptr, func));
|
||||
slots_.push_back(new BoundMemberMethod<T, R, Args...>(obj, nullptr, func));
|
||||
}
|
||||
|
||||
void connect(void (*func)(Args...))
|
||||
template<typename R>
|
||||
void connect(R (*func)(Args...))
|
||||
{
|
||||
slots_.push_back(new BoundStaticMethod<Args...>(func));
|
||||
slots_.push_back(new BoundStaticMethod<R, Args...>(func));
|
||||
}
|
||||
|
||||
void disconnect()
|
||||
@@ -90,11 +91,12 @@ public:
|
||||
SignalBase::disconnect(obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void disconnect(T *obj, void (T::*func)(Args...))
|
||||
template<typename T, typename R>
|
||||
void disconnect(T *obj, R (T::*func)(Args...))
|
||||
{
|
||||
for (auto iter = slots_.begin(); iter != slots_.end(); ) {
|
||||
BoundMethodArgs<Args...> *slot = static_cast<BoundMethodArgs<Args...> *>(*iter);
|
||||
BoundMethodArgs<R, Args...> *slot =
|
||||
static_cast<BoundMethodArgs<R, Args...> *>(*iter);
|
||||
/*
|
||||
* If the object matches the slot, the slot is
|
||||
* guaranteed to be a member slot, so we can safely
|
||||
@@ -102,7 +104,7 @@ public:
|
||||
* func.
|
||||
*/
|
||||
if (slot->match(obj) &&
|
||||
static_cast<BoundMemberMethod<T, Args...> *>(slot)->match(func)) {
|
||||
static_cast<BoundMemberMethod<T, R, Args...> *>(slot)->match(func)) {
|
||||
iter = slots_.erase(iter);
|
||||
delete slot;
|
||||
} else {
|
||||
@@ -111,12 +113,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void disconnect(void (*func)(Args...))
|
||||
template<typename R>
|
||||
void disconnect(R (*func)(Args...))
|
||||
{
|
||||
for (auto iter = slots_.begin(); iter != slots_.end(); ) {
|
||||
BoundMethodArgs<Args...> *slot = *iter;
|
||||
BoundMethodArgs<R, Args...> *slot = *iter;
|
||||
if (slot->match(nullptr) &&
|
||||
static_cast<BoundStaticMethod<Args...> *>(slot)->match(func)) {
|
||||
static_cast<BoundStaticMethod<R, Args...> *>(slot)->match(func)) {
|
||||
iter = slots_.erase(iter);
|
||||
delete slot;
|
||||
} else {
|
||||
@@ -133,7 +136,7 @@ public:
|
||||
*/
|
||||
std::vector<BoundMethodBase *> slots{ slots_.begin(), slots_.end() };
|
||||
for (BoundMethodBase *slot : slots)
|
||||
static_cast<BoundMethodArgs<Args...> *>(slot)->activate(args...);
|
||||
static_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace libcamera {
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn Signal::connect(T *object, void(T::*func)(Args...))
|
||||
* \fn Signal::connect(T *object, R (T::*func)(Args...))
|
||||
* \brief Connect the signal to a member function slot
|
||||
* \param[in] object The slot object pointer
|
||||
* \param[in] func The slot member function
|
||||
@@ -66,7 +66,7 @@ namespace libcamera {
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn Signal::connect(void(*func)(Args...))
|
||||
* \fn Signal::connect(R (*func)(Args...))
|
||||
* \brief Connect the signal to a static function slot
|
||||
* \param[in] func The slot static function
|
||||
*/
|
||||
@@ -83,14 +83,14 @@ namespace libcamera {
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn Signal::disconnect(T *object, void(T::*func)(Args...))
|
||||
* \fn Signal::disconnect(T *object, R (T::*func)(Args...))
|
||||
* \brief Disconnect the signal from the \a object slot member function \a func
|
||||
* \param[in] object The object pointer whose slots to disconnect
|
||||
* \param[in] func The slot member function to disconnect
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn Signal::disconnect(void(*func)(Args...))
|
||||
* \fn Signal::disconnect(R (*func)(Args...))
|
||||
* \brief Disconnect the signal from the slot static function \a func
|
||||
* \param[in] func The slot static function to disconnect
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user