如何阅读模板偏特化?

3
假设有以下声明:

假设有以下声明:

template <typename T> struct MyTemplate;

下面关于部分特化的定义似乎使用同一个字母 T 来指代不同的类型。
template <typename T> struct MyTemplate<T*> {};

例如,让我们来看一个具体的实例:
MyTemplate<int *> c;

现在,请再次考虑上述偏特化定义:

对于类模板的偏特化,它是一种在给定部分类型参数时,对原始类模板进行专门设计和优化的技术。

template <typename T> struct MyTemplate<T*> {};

在这行代码的第一部分(即template <typename T>)中,Tint *。在这行代码的第二部分(即MyTemplate<T*>)中,Tint
那么,如何阅读这个偏特化的定义呢?

2
T * 中的 T 替换为 int,你就得到了 int * - Potatoswatter
它类似于普通参数:在int foo(int a)void bar(int a)void foobar(std::string&a)中的a不是同一个。 - Jarod42
我理解定义的效果。然而,在同一行代码中使用相同的字母表示两种不同的类型对我来说没有意义。这就像有一个T(T),它会被解析为int *(int)... 我已经编辑了问题以强调这一点。 - AlwaysLearning
你是正确的。我该如何读取它? - AlwaysLearning
1
在这行代码的第一部分(即template <typename T>),T是int ,这是错误的。你为什么会这样认为呢?如果你假设调用中的int以某种方式映射到T,那么不,它并不是这样的。 - n. m.
4个回答

6

请按照以下方式阅读:

  1. The primary template says "MyTemplate is a class template with one type parameter":

    template <typename> struct MyTemplate;
    
  2. The partial specialization says, "whenever there exists a type T"...

    template <typename T>
    

    ... such that a specialization of MyTemplate is requested for the type T *"...

    struct MyTemplate<T *>
    

    ... then use this alternative definition of the template.

  3. You could also define explicit specializations. For example, could say "whenever the specialization is requested for type X, use this alternative definition:

    template <> struct MyTemplate<X> { /* ... */ };
    
请注意,类模板的显式特化定义类型,而部分特化定义模板。
换句话说,部分类模板特化推导匹配类模板参数的结构:
template <typename T> struct MyTemplate<T *>
//       ^^^^^^^^^^^^                  ^^^^^
//       This is a new template        Argument passed to the original class
//                                     template parameter

这个新模板的参数名称在结构上与原始类模板的参数进行匹配。
举例:
- `MyTemplate`:类模板的类型参数为`void`,并且该专业模板用于这个特化。 - `MyTemplate`:类型参数是`int *`。存在一个类型`T`,即`T = int`,请求的类型参数是`T *`,因此模板的部分特化定义用于这个特化。 - `MyTemplate`:参数类型为`X`,已为该参数类型定义了显式特化,因此使用该特化。

2
正确的读法是专业化(specialisation)。
template <typename T> // a *type pattern* with a *free variable* `T` follows
struct MyTemplate<T*> // `T*` is the pattern

当模板被实例化为 MyTemplate<int*> 时,参数与模式匹配,而不是类型变量列表。然后从匹配中推导出类型变量的值。
为了更直接地理解这一点,请考虑一个具有两个参数的模板。
template <typename T1, typename T2>
struct A;

及其专业化

template <typename T1, typename T2>
struct A<T1*, T2*>;

现在你可以把后者写成

template <typename T2, typename T1>
struct A<T1*, T2*>;

变量列表的顺序被颠倒,这与之前的等效。事实上,列表中的顺序并不重要。当您调用A<int*, double*>时,会推断出T1=intT2=double,而不管模板头中T1和T2的顺序如何。

此外,您可以这样做

template <typename T>
struct A<T*, T*>;

并在 A<int*, int*> 中使用它。现在很清楚,类型变量列表与实际模板参数列表没有直接对应关系。

注意:术语“模式”、“类型变量”、“类型模式匹配”不是标准的 C++ 术语。但几乎在任何其他地方都是标准术语。


似乎有一个笔误:在倒序排列中,T2出现了两次。 - AlwaysLearning

0

没有矛盾。T应该被读作T,T*是T*。

template <typename T> struct MyTemplate<T*> {};

“在这一行的第一部分中(即template <typename T>),T是int *。”

不对 - 在template <typename T>中,T是int,在struct MyTemplate<T*> {};中,T也是int。

“请注意,当使用部分特化时,模板参数是从专业模式中推导出来的;模板参数并不仅仅是实际的模板参数。特别地,对于Vector<Shape*>,T是Shape而不是Shape*。”(Stroustrup C ++,第4版,25.3,p.732。)


0
你有这一行代码:
MyTemplate<int *> c;

你的困惑似乎来自于认为< >中的int *template <typename T>中的T有什么联系。实际上并没有。在一个部分特化(实际上是在每个模板声明)中,模板参数名只是“自由变量”(或者可能是“占位符”)名称。模板参数(在你的情况下是int *)不直接对应这些,它们对应于跟随模板名称的<>中的内容。
这意味着实例化的<int *>部分映射到部分特化的<T*>部分。T只是由template <typename T>前缀引入的一个名字。在整个过程中,Tint

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接