我不能像这样添加指针变量(既不是常量也不是静态的)
template <> struct s<MyClass *obj > // ERROR
[...]
你可能在这里有一个误解。如果您关心希望提供指向用户定义类的实例的指针作为非类型模板参数的用例,那么这与模板专业化无关。
特别是,根据 C++11 标准的第 14.3.2/1 段,考虑您可以将指向类的全局实例的指针指定为模板参数:
非类型、非模板模板参数的模板参数应为以下之一:
——对于整数或枚举类型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或者
— 非类型模板参数的名称;或者
— 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 (忽略括号)作为 & id 表达式,但如果名称引用函数或数组,则 & 可以省略,如果相应的模板参数是引用,则应省略;或者
[...]
这可能是您想要实现的目标:
struct MyClass { };
MyClass c;
template<MyClass* p>
// ^^^^^^^^ Non-type template argument
struct s
{
// Possibly work with p
};
int main()
{
s<&c> obj;
}
关于模板专业化:
关于您编写的代码,您的主模板可以处理任何类型:
template <typename T> struct s
{
// Definition...
};
当用于实例化主模板的参数为MyClass*
:
template <> struct s<MyClass *>
{
// Definition when the template argument is `MyClass*`
};
例如,您可以这样做:
struct MyClass { };
template <typename T> struct s
{
void print() { cout << "Primary template!" << endl; }
};
template <> struct s<MyClass *>
{
void print() { cout << "Specialization for MyClass*!" << endl; }
};
int main()
{
s<int> obj;
obj.print(); // Will print "Primary template!"
s<MyClass*> obj;
obj.print(); // Will print "Specialization for MyClass*!"
}
另请注意,专用模板的定义可能与主模板的定义完全不同:
template <typename T> struct s
{
void print() { cout << "Primary template!" << endl; }
};
template <> struct s<MyClass *>
{
void greet() { cout << "Specialization for MyClass*!" << endl; }
};
int main()
{
s<int> obj;
obj.print(); // Will print "Primary template!"
s<MyClass*> obj;
obj.greet(); // Will print "Specialization for MyClass*!"
obj.print(); // ERROR! s<MyClass*> has no `print()` member function
}
当然,这只是类模板特化如何工作的一个示例。以我的方式区分主要模板和专用模板的定义没有任何用处。
但是,存在许多用于此的实际用例。例如,可以针对某些特定类型以完全不同的方式优化和重写通用算法。
模板专业化的另一个重要应用是定义特征,您可能想了解它。