【问题标题】:How can I acquire the basic function type from an std::function?如何从 std::function 获取基本函数类型?
【发布时间】:2012-08-21 21:22:16
【问题描述】:

我有很多 typedef 为 std::function<void(PARAMS)> 的类,其中 PARAMS 特定于每个类。我需要根据参数的数量和第一个参数的类型进行专门研究。我想为此使用boost::function_traits,但为了使用它,我需要有相关std::function 的原始函数类型。

例如,给定std::function<void(int,int)>,我想检索void(int,int)

有没有办法以可移植的方式提取本机类型?附带说明一下,我无权访问 C++11 功能。

【问题讨论】:

  • std::function 在 C++11 中是新的,你怎么不使用它呢?
  • std::function 是 TR1 的一部分。我省略了 tr1 命名空间。如此迂腐对任何人都没有好处。
  • 那么请告诉我们您无法访问哪些 C++11 功能,也许您已经在 TR1 中拥有它
  • @dauphic:他并没有迂腐,他只是指出了你问题中明显的困惑。您声称没有可用的 C++11,但您想推理 C++11 的东西(如果您使用 tr1,那么您肯定会告诉我们您使用 std::tr1::function,所以这很令人困惑)。此外,大多数人提出问题并说“没有 C++11”的意思是“只有 C++03”
  • @dauphic: std::function 是一个可变参数模板,因此当它移动到std 命名空间时,它会升级为可变参数模板(前提是您的编译器支持该功能)。跨度>

标签: c++ function tr1 typetraits


【解决方案1】:

要获取函数类型,可以使用偏特化:

template <typename T>
struct Detect;

template <typename F>
struct Detect<std::function<F>> {
  typedef F Result;
};

现在当你得到一个未知的std::function&lt;?&gt; 类型T,你只需使用

typename Detect<T>::Result

(您可能希望将Result 定义为F *,因为某些上下文(例如,字段类型)仅允许指向函数的指针,而不是裸函数类型。

编辑:

要专注于参数的数量和第一个参数的类型,您需要 C++11 可变参数模板

template <typename T>
struct Detect;

template <typename R, typename A, typename... As>
struct Detect<std::function<R(A,As...)>> {
  static constexpr auto numargs = 1 + sizeof...(As);
  typedef R Result;
  typedef A FirstArg;
};

或编写与上述等效的代码,对每个可能的参数数量使用单独的特化:

template <typename R, typename A1>
struct Detect<std::function<R(A1)>> {
  enum { numargs = 1 };
  typedef R Result;
  typedef A1 FirstArg;
};

template <typename R, typename A1, typename A2>
struct Detect<std::function<R(A1,A2)>> {
  enum { numargs = 2 };
  ...
};

...

【讨论】:

  • typedef std::tuple&lt;Args...&gt; parameter_types; static std::size_t const num_parameters = sizeof...(Args);
【解决方案2】:

std::function 包含 result_typeargument_type 用于一元函数,first_argument_typesecond_argument_type 用于二元函数。你可以提取这些。对于使用可变参数模板定义的n-ary 函数,我认为没有包含所有参数的std::tuple

如果你想要自己的特质类:

template<typename Fun>
struct function_traits;

template<typename R, typename... Args>
struct function_traits<std::function<R(Args...)>
{
    typedef R return_type;
    typedef std::tuple<Args...> arguments_type;
};

【讨论】:

  • 您似乎在这里犯了一个小错误——function_traits 的非专业声明有多个参数,而不仅仅是一个参数(您为其提供了一个 std::function&lt;...&gt;;这“偶然”有效",Args 始终为空 :)
  • 仍然错误(现在它甚至无法编译)——只需使用template &lt;typename&gt; class function_traits;;另外,使它成为一个结构,或者在提取的特征之前添加public:! :)
  • @GrzegorzHerman 夏季,温度正在煮我的大脑 :-)
  • 这里已经快午夜了,所以温度要好得多 :)
  • 在部分规范中使用Args&amp;&amp; 会使事情大错特错,按值参数变为右值引用。不要这样做。
【解决方案3】:

创建一个元函数来提取boost::function&lt;T&gt;中的T应该足够简单

template<typename T>
struct func_extractor

template<typename T>
struct func_extractor<boost::function<T> >
{
   typedef T type;
};

int main()
{
    typedef boost::function<void(int, int)> func_type1; 
    typedef func_extractor<func_type1>::type extracted_type;
    typedef boost::function<extracted_type> func_type2;
    std::cout << boost::is_same<func_type1, func_type2>::value << std::endl;
}

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2018-09-02
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多