假设:
- 您只需要返回类型。
- 您不知道参数类型是什么/将是什么(因此
decltype() 和std::result_of<> 都不是一个选项。
- 作为参数传递的仿函数对象不会有重载或泛型
operator()。
然后您可以使用以下特征来推断任何函子对象的返回类型:
template <typename F>
struct return_type_impl;
template <typename R, typename... Args>
struct return_type_impl<R(Args...)> { using type = R; };
template <typename R, typename... Args>
struct return_type_impl<R(Args..., ...)> { using type = R; };
template <typename R, typename... Args>
struct return_type_impl<R(*)(Args...)> { using type = R; };
template <typename R, typename... Args>
struct return_type_impl<R(*)(Args..., ...)> { using type = R; };
template <typename R, typename... Args>
struct return_type_impl<R(&)(Args...)> { using type = R; };
template <typename R, typename... Args>
struct return_type_impl<R(&)(Args..., ...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) &> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) &> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) &&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) &&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile&&> { using type = R; };
template <typename T, typename = void>
struct return_type
: return_type_impl<T> {};
template <typename T>
struct return_type<T, decltype(void(&T::operator()))>
: return_type_impl<decltype(&T::operator())> {};
template <typename T>
using return_type_t = typename return_type<T>::type;
测试:
#include <type_traits>
template <typename F>
void test(F h)
{
static_assert(std::is_same<return_type_t<F>, int>{}, "!");
return_type_t<F> i = 1;
}
int function(int i) { return 2*i; }
int c_varargs_function(...) { return 1; }
struct A
{
int mem_function(double, float) { return 1; }
};
int main()
{
// Function
test(function);
// C-style variadic function
test(c_varargs_function);
// Non-generic lambda
test([](int i) { return 2*i; });
// Member function
test(&A::mem_function);
}
DEMO