From be4a16cd4188ebeeba60768deadd88de5cc5be7b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 6 Dec 2018 21:23:07 +0900 Subject: function_traits<>: support any arity; add compile-time tests --- lib/util.h | 68 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 20 deletions(-) (limited to 'lib/util.h') diff --git a/lib/util.h b/lib/util.h index 88c756a1..3f5bcb5f 100644 --- a/lib/util.h +++ b/lib/util.h @@ -119,41 +119,69 @@ namespace QMatrixClient bool _omitted = false; }; + namespace _impl { + template struct fn_traits; + } + /** Determine traits of an arbitrary function/lambda/functor - * This only works with arity of 1 (1-argument) for now but is extendable - * to other cases. Also, doesn't work with generic lambdas and function - * objects that have operator() overloaded + * 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 function_traits - { }; // A generic function object that has (non-overloaded) operator() + struct function_traits : public _impl::fn_traits {}; // Specialisation for a function - template - struct function_traits + template + struct function_traits { + static constexpr auto is_callable = true; using return_type = ReturnT; - using arg_type = ArgT; + using arg_types = std::tuple; + static constexpr auto arg_number = std::tuple_size::value - 1; }; - // Specialisation for a member function - template - struct function_traits - : function_traits - { }; + namespace _impl { + template + struct fn_traits + { + static constexpr auto is_callable = false; + }; + + template + struct fn_traits + : public fn_traits + { }; // A generic function object that has (non-overloaded) operator() - // Specialisation for a const member function - template - struct function_traits - : function_traits - { }; + // Specialisation for a member function + template + struct fn_traits + : function_traits + { }; + + // Specialisation for a const member function + template + struct fn_traits + : function_traits + { }; + } // namespace _impl template using fn_return_t = typename function_traits::return_type; - template - using fn_arg_t = typename function_traits::arg_type; + template + using fn_arg_t = + std::tuple_element_t::arg_types>; + + template + constexpr bool returns() + { + return std::is_same, R>::value; + } + + // Poor-man's is_invokable + template + constexpr auto is_callable_v = function_traits::is_callable; inline auto operator"" _ls(const char* s, std::size_t size) { -- cgit v1.2.3