功能签名的专用模板

时间:2012-12-14 23:23:40

标签: c++ templates template-specialization function-signature

在该测试代码中:

#include <string>
#include <iostream>

using namespace std;

template <typename T> class Signal;

template <typename T, typename U>
class Signal<T (U)>
{
public:
  Signal<T (U)>(T (*ptr)(U))
  {
  }
};

void Print(string const& str)
{
  cout << str << endl;
}

int main(int argc, char *argv[])
{
  Signal<void (string const&)> sig = &Print;
  return 0;
}

为什么我要写template <typename T> class Signal;

为什么我必须指定它?

2 个答案:

答案 0 :(得分:3)

没有去做你正在做的事情,但这是最灵活的方法。具有专业化的单参数模板如下:

  • 在一种类型上参数化的模板...

    template <typename> struct Foo;
    
  • ...但仅为功能类型定义:

    template <typename R>
    struct Foo<R()> { /* ... */ };
    
    template <typename R, typename A1>
    struct Foo<R(A1)> { /* ... */ };
    
    template <typename R, typename ...Args>
    struct Foo<R(Args...)> { /* ... */ };
    

另一种方法是硬编码函数的签名:

  • 存储单参数函数的函数指针的类模板:

    template <typename R, typename A>
    struct Bar
    {
        R (*fp)(A);
        Bar(R(*f)(A)) : fp(f) { }
        // ...
    };
    

正如您所看到的,第一种方法更为通用,因为我们可以为我们喜欢的任何函数类型专门化Foo。相比之下,第二个例子中的直接模板与函数签名的细节错综复杂地联系在一起,不容易推广。

答案 1 :(得分:2)

您正在创建Signal的专精,它将任意类型TU合并到T(U)形式中。这是专门化Signal<T(U)>:参数中只有一种类型,这就是为什么我们前向声明Signal只采用一种类型T。没有这一声明,这是不可能的。

这是一个简单的例子:

template <typename T> struct A;

template <typename T, typename U> struct A<T(U)> {

};

int main() {

    A<void(int)> a;

}

voidint类型分别与TU类型绑定。这将合并到void(int)主要声明中使用的A类型中,以专门化该类。