【问题标题】:c++11 get type of first (second, etc...) argument, similar to result_ofc++11获取第一个(第二个等)参数的类型,类似于result_of
【发布时间】:2015-01-10 18:39:35
【问题描述】:

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

我可以用 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;
}

编译器在推导 A 和 B 时有问题(尤其是当它不是 std::function 而是 lambda 时),所以这不是正确的方法。)

【问题讨论】:

  • 这是否描述了您的问题? stackoverflow.com/questions/27851111/…
  • 仅限于您​​列出的三种情况(std::function、C++11(非泛型)lambda 和普通函数指针),这是可行的,但无法推广到任意函子或泛型lambdas。
  • 5gon12eder, WhozCraig:谢谢,但不是真的,在这些情况下,他们并不真正想要传递函数的参数。
  • T.C.:当然,它必须从somewhere获取类型。

标签: c++ templates c++11


【解决方案1】:

这不适用于泛型 lambda 或 operator() 重载或为模板的任意函子。

// 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.

【讨论】:

  • 这种方法在Boost.CallableTraits中实现,见args_t in boost.org/doc/libs/1_68_0/libs/callable_traits/doc/html/…
  • @olq_plo,如何使用 boost::callable_traits 获取可调用的 N'th arg 类型?
  • @Sergei args_t 返回一个std::tuple,因此您使用std::tuple_element 来获取第N 个参数。
【解决方案2】:

#include &lt;boost/type_traits.hpp&gt;

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

【讨论】:

  • 只有代码的答案是不够的。请添加此代码 sn-p 如何回答问题的说明。
  • function_traits 被 callable_traits 取代
猜你喜欢
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多