From dc08fb9dfd474023084de9ce86f29f177ca52fdc Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 2 Dec 2021 15:24:44 +0100 Subject: Improve function_traits<>; split out from util.* Quotient::function_traits<> did not support member functions in a proper way (i.e. the way std::invoke_result<> treats them, with the function's owning class represented as the first parameter). Now that I gained the skill and understanding in function_traits<> somewhat wicked machinery, I could properly support member functions. Overloads and generic lambdas are not supported but maybe we'll get to those one day. --- lib/function_traits.h | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 lib/function_traits.h (limited to 'lib/function_traits.h') diff --git a/lib/function_traits.h b/lib/function_traits.h new file mode 100644 index 00000000..83b8e425 --- /dev/null +++ b/lib/function_traits.h @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2018 Kitsune Ral +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include + +namespace Quotient { + +namespace _impl { + template + struct fn_traits {}; +} + +/// Determine traits of an arbitrary function/lambda/functor +/*! + * Doesn't work with generic lambdas and function objects that have + * operator() overloaded. + * \sa + * https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda#7943765 + */ +template +struct function_traits + : public _impl::fn_traits> {}; + +// Specialisation for a function +template +struct function_traits { + using return_type = ReturnT; + using arg_types = std::tuple; + // See also the comment for wrap_in_function() in qt_connection_util.h + using function_type = std::function; +}; + +namespace _impl { + template + struct fn_object_traits; + + // Specialisation for a lambda function + template + struct fn_object_traits + : function_traits {}; + + // Specialisation for a const lambda function + template + struct fn_object_traits + : function_traits {}; + + // Specialisation for function objects with (non-overloaded) operator() + // (this includes non-generic lambdas) + template + struct fn_traits + : public fn_object_traits {}; + + // Specialisation for a member function in a non-functor class + template + struct fn_traits + : function_traits {}; + + // Specialisation for a const member function + template + struct fn_traits + : function_traits {}; + + // Specialisation for a constref member function + template + struct fn_traits + : function_traits {}; + + // Specialisation for a prvalue member function + template + struct fn_traits + : function_traits {}; + + // Specialisation for a pointer-to-member + template + struct fn_traits + : function_traits {}; + + // Specialisation for a const pointer-to-member + template + struct fn_traits + : function_traits {}; +} // namespace _impl + +template +using fn_return_t = typename function_traits::return_type; + +template +using fn_arg_t = + std::tuple_element_t::arg_types>; + +} // namespace Quotient -- cgit v1.2.3