c++11 获取第一个(第二个等...)参数的类型,类似于 result_of

c++11 get type of first (second, etc...) argument, similar to result_of

假设我有一个模板函数,它接受一个参数,它是一个函数(它可以是 std::function,或 lambda,或实际的函数指针)。一个说明问题的愚蠢例子:

template<typename F,typename A,typename B = typename std::result_of<F(A)>::type>
B blabla(F &&f)
{
    return f(A())/3;
}

如果我有 A 的类型,我可以用 std::result_of::typename 引用 f 的 return 类型,但我希望编译器从 F 的第一个参数推断出类型 A。 (如果我写

template<typename A,typename B>
B blabla(const std::function<B(A)> &f)
{
    return f(A())/3;
}

编译器在推导 A 和 B 时遇到问题(特别是如果它不是 std::function 而是 lambda),所以这不是正确的方法。)

这不适用于 operator() 重载或为模板的通用 lambda 或任意仿函数。

// primary template.
template<class T>
struct function_traits : function_traits<decltype(&T::operator())> {
};

// partial specialization for function type
template<class R, class... Args>
struct function_traits<R(Args...)> {
    using result_type = R;
    using argument_types = std::tuple<Args...>;
};

// partial specialization for function pointer
template<class R, class... Args>
struct function_traits<R (*)(Args...)> {
    using result_type = R;
    using argument_types = std::tuple<Args...>;
};

// partial specialization for std::function
template<class R, class... Args>
struct function_traits<std::function<R(Args...)>> {
    using result_type = R;
    using argument_types = std::tuple<Args...>;
};

// partial specialization for pointer-to-member-function (i.e., operator()'s)
template<class T, class R, class... Args>
struct function_traits<R (T::*)(Args...)> {
    using result_type = R;
    using argument_types = std::tuple<Args...>;
};

template<class T, class R, class... Args>
struct function_traits<R (T::*)(Args...) const> {
    using result_type = R;
    using argument_types = std::tuple<Args...>;
};

// additional cv-qualifier and ref-qualifier combinations omitted
// sprinkle with C-style variadics if desired

然后

template<class T>
using first_argument_type = typename std::tuple_element<0, typename function_traits<T>::argument_types>::type;

根据需要将 0 替换为所需的数字,或编写一个单独的别名,该别名也带有索引。 Demo.

#include <boost/type_traits.hpp>

boost::function_traits<decltype(function)>::arg2_type