4

在该测试代码中:

#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;

为什么我必须指定它?

4

2 回答 2

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针对我们喜欢的任何函数类型。相比之下,第二个示例中的直接模板与函数签名的细节错综复杂地联系在一起,不容易泛化。

于 2012-12-14T23:46:49.883 回答
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

于 2012-12-14T23:34:00.660 回答