[libcamera-devel] [PATCH 2/2] libcamera: object: Support reference arguments in invokeMethod()

Paul Elder paul.elder at ideasonboard.com
Fri Jan 3 06:33:45 CET 2020


Hi Laurent,

Thank you for the patch.

On Fri, Jan 03, 2020 at 01:53:11AM +0200, Laurent Pinchart wrote:
> Invoking a method that takes a reference argument with
> Object::invokeMethod() results in a compilation error:
> 
> ../test/object-invoke.cpp:131:11: error: no matching member function for call to 'invokeMethod'
>                 object_.invokeMethod(&InvokedObject::methodWithReference,
>                 ~~~~~~~~^~~~~~~~~~~~
> ../include/libcamera/object.h:33:7: note: candidate template ignored: deduced conflicting types for parameter 'Args' (<const int &> vs. <int>)
>         void invokeMethod(void (T::*func)(Args...), ConnectionType type, Args... args)
> 
> This is due to the fact that implicit type conversions (from value to
> reference in this case) takes place after template argument type
> deduction, during overload resolution. A similar issue would occur if
> T::func took a long argument and invokeMethod() was called with an in
> argument.
> 
> Fix this by specifying to sets of argument types in the invokeMethod()
> template, one for the arguments to the invoked method, and one for the
> arguments to invokeMethod() itself. The compiler can then first perform
> type deduction separately, and implicit conversion in a second step.
> 
> Reported-by: Paul Elder <paul.elder at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  include/libcamera/object.h | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/include/libcamera/object.h b/include/libcamera/object.h
> index 86e0f7265865..21b70460b516 100644
> --- a/include/libcamera/object.h
> +++ b/include/libcamera/object.h
> @@ -29,13 +29,15 @@ public:
>  
>  	void postMessage(std::unique_ptr<Message> msg);
>  
> -	template<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
> -	void invokeMethod(void (T::*func)(Args...), ConnectionType type, Args... args)
> +	template<typename T, 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,
> +			  Args... args)
>  	{
>  		T *obj = static_cast<T *>(this);
>  		BoundMethodBase *method =
> -			new BoundMemberMethod<T, Args...>(obj, this, func, type);
> -		void *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... };
> +			new BoundMemberMethod<T, FuncArgs...>(obj, this, func, type);
> +		void *pack = new typename BoundMemberMethod<T, FuncArgs...>::PackType{ args... };
>  
>  		method->activatePack(pack, true);
>  	}

Ooh, fancy template magic.

Looks good to me.

Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>


More information about the libcamera-devel mailing list