在该测试代码中:
#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;
?
为什么我必须指定它?
答案 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
的专精,它将任意类型T
和U
合并到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;
}
void
和int
类型分别与T
和U
类型绑定。这将合并到void(int)
主要声明中使用的A
类型中,以专门化该类。