模板参数中的类指针 - 这对什么有用?

时间:2013-03-02 14:10:48

标签: c++ templates

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 *&#34;匿名&#34;指针

2 个答案:

答案 0 :(得分:1)

  

我无法添加指针变量(既不是常量也不是静态),如

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

你可能在这里有误解。如果您关注要将用户定义类的实例指针作为非类型模板参数提供的用例,那么这与模板 specialization 无关。

特别要考虑到可以指定一个指向类的全局实例的指针作为模板参数,根据C的第14.3.2 / 1节++ 11标准:

  

非类型非模板模板参数的模板参数应为以下之一:

     

- 对于整数或枚举类型的非类型模板参数,转换的常量表达式   (5.19)模板参数的类型;或

     

- 非类型模板参数的名称;或

     

- 一个常量表达式(5.19),用于指定具有静态存储持续时间的对象的地址   外部或内部链接或具有外部或内部链接的功能,包括功能模板   和函数template-ids但不包括非静态类成员,表示(忽略括号)为   &安培; id-expression,除了&amp;如果名称引用函数或数组,则可以省略   如果相应的模板参数是引用,则省略;或

     

[...]

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

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...
};

这个显式特化(这是技术名称,而不是“total”specialization)允许您在用于实例化主模板的参数为{时,重新定义主模板的内容{1}}:

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*!"
}

当然,这只是类模板专业化工作原理的一个例子。用我的方式区分主要模板和专用模板的定义没什么用。

然而,存在许多现实世界的用例。例如,对于某些特定类型,可以以完全不同的方式优化和重写通用算法。

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

答案 1 :(得分:0)

实例化模板(隐式或显式)时,提供类型:

s<int> s1;
s<float> s2;
s<MyClass> s3;

这些对象将分别是模板s的实例化,T分别推导到intfloatMyClass。例如,如果s实际定义如此:

template <typename T> struct s {
  T x;
};

然后,对象s1有一个名为x的成员ints2有一个名为x的成员floats3有一个名为x MyClass的成员。

您提供的显式特化的要点是,当传递给模板参数的类型为s时,提供MyClass*的不同实现,如:

s<MyClass*> s4;

例如,考虑一个看起来像:

的显式特化
template <> struct s<MyClass*>
{
  int x;
};

对象s4尽管其模板参数为MyClass*,但仍会有一个名为x的成员int。我们特地说“当模板参数类型为MyClass*时,结构将有一个成员int x。”

s4对象将使用s的显式特化,而不是更通用的版本。当您知道模板参数为MyClass*时,也许您可​​以更有效地实现您的类。