c ++ 11获取first(second,etc ...)类型的类型,类似于result_of

Zso*_*ari 7 c++ templates c++11

假设我有一个模板函数,它接受一个参数,它是一个函数(它可以是一个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;
}
Run Code Online (Sandbox Code Playgroud)

我可以用std :: result_of :: typename引用f的返回类型,因为我的类型是A,但是我希望编译器从F的第一个参数中推断出类型A. (如果我写的话

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

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

T.C*_*.C. 13

这对于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
Run Code Online (Sandbox Code Playgroud)

然后

template<class T>
using first_argument_type = typename std::tuple_element<0, typename function_traits<T>::argument_types>::type;
Run Code Online (Sandbox Code Playgroud)

根据需要将0替换为所需的数字,或者写一个也采用索引的别名.演示.