template <typename T> struct s
{

};

template <> struct s<MyClass *>
{

};

... in main function
struct s<MyClass*> obj;


上面的代码可以编译,但是我真的看不到完全专业化能做什么

template <> struct s<MyClass *>
{

};


我不能像这样添加指针变量(既不是常量也不是静态的)

template <> struct s<MyClass *obj > // ERROR
{

};


那么上面的专业化有什么意义呢?我不能使用MyClass *“匿名”指针

最佳答案

我不能像这样添加指针变量(既不是常量也不是静态的)


template <> struct s<MyClass *obj > // ERROR
[...]


您可能在这里有一个误解。如果您担心要为非自定义模板参数提供指向用户定义类实例的指针的用例,则这与模板专门化无关。

特别是,请考虑按照C ++ 11标准的14.3.2 / 1段,可以将指向类的全局实例的指针指定为模板参数:


  非类型,非模板模板参数的模板参数应为以下之一:
  
  —对于整数或枚举类型的非类型模板参数,转换后的常数表达式
  (5.19)模板参数的类型;要么
  
  —非类型模板参数的名称;要么
  
  —一个常数表达式(5.19),用于指定具有静态存储持续时间的对象的地址,以及
  外部或内部链接或具有外部或内部链接的功能,包括功能模板
  和函数模板ID,但不包括非静态类成员,表示为(忽略括号)为
  &id-expression,但如果名称引用了函数或数组,则&可以省略,并且应
  如果相应的模板参数是参考,则省略;要么
  
  [...]


这可能是您想要实现的目标:

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
}


当然,这只是类模板专业化工作方式的一个示例。在区分主要模板和专用模板的定义方面,没有什么用处。

但是,存在许多实际的用例。例如,可以针对某种特定类型以完全不同的方式优化和重写通用算法。

模板专业化的另一个重要应用是定义特征,您可能想要阅读这些特征。

09-30 15:33
查看更多