C ++理解复杂函数签名

时间:2015-03-16 09:09:58

标签: c++

在阅读一些代码时,我遇到了这个功能。我很难理解函数的签名。在我能够制作以下代码的头部或尾部之前,我需要知道的是什么? 我一直在使用C ++一段时间。我知道模板,函数指针是什么。但是,我无法弄清楚T::*可能意味着什么,以_Defer开头的行在语义上意味着什么。 此外,该功能的第一行似乎非常令人生畏。在尝试重新评估此代码之前,是否有一些我可以阅读的资源?

template <typename T>
_Defer<void(*(PID<T>, void (T::*)(void)))
       (const PID<T>&, void (T::*)(void))>
defer(const PID<T>& pid, void (T::*method)(void))
{
  void (*dispatch)(const PID<T>&, void (T::*)(void)) =
    &process::template dispatch<T>;
  return std::tr1::bind(dispatch, pid, method);
}

来源:https://github.com/3rdparty/libprocess/blob/master/include/process/defer.hpp

2 个答案:

答案 0 :(得分:5)

这可能有助于澄清一些事情:

template<typename T>
using VoidPMemberFn = void(T::*)(); // Pointer to member function of T
                                    // that accepts no arguments and
                                    // returns nothing.

template<typename T>
using DeferResultType = void (*)(const PID<T> &, VoidPMemberFn<T>);

template<typename T>
using DeferSignatureType = DeferResultType<T>(PID<T>, VoidPMemberFn<T>);

template<typename T>
_Defer<DeferSignatureType<T>> defer(const PID<T> &pid, VoidPMemberFn<T> method)
{
    // Stuff...
}

修改

这可能有助于澄清_Defer模板中意大利面的含义,以及它与上述内容的关系:

void(* (PID<T>, void (T::*)(void)) )(const PID<T>&, void (T::*)(void))
^-+^-^ ^-------------------------^  ^-------------+------------------^
  |           argument list                       |
  |                                               |
  +-----------------------------------------------+
              return type:  void(*)(const PID<T> &, void(T::*)(void))

这会创建一个“签名”,就像std::function一样(例如std::function<int(float)>)。

更多例子:

using sig = int(float);

sig gn; // Same as: "int gn(float)", a function declaration

int fn(float x)
{return (int)x;}

int main(int argc, char **argv)
{
    // pointer to a function with signature "sig"
    sig *pfn = &fn;
    return 0;
}

int gn(float x)
{return (int)(x*x);}

答案 1 :(得分:0)

这是非标准的非便携式代码,因此很难为人类解码。返回类型

_Defer<void(*(PID<T>, void (T::*)(void)))(const PID<T>&, void (T::*)(void))>

是包含在某些标头中定义的某些类模板_Defer的特化。这是在defube的答案中解释的。

但是,_Defer<>不是std库规范的一部分,因此以这种方式使用它会使代码不可移植,因此符合非标准。使用std::tr1::bind代替std::bind也是如此。

我猜你的函数的C ++ 14等价只是

template <typename T>
auto defer(const PID<T>& pid, void (T::*method)())
{
  auto dispatch = &process::template dispatch<T>;
  return std::bind(dispatch, pid, method);
}

其中process必须是某个类(或基类,如果defer是成员函数),并且具有静态模板成员方法dispatch。因此,defer()返回一些函数对象(参见documentation for std::bind)以便稍后调用。

请注意,标准的返回类型std::bind 未指定,因此auto(或将其打包成std::function)是唯一的可移植方式处理它。