提问人:Chris Gnam 提问时间:7/3/2023 更新时间:7/4/2023 访问量:64
写作/口语时如何区分不同类型的 C++ 专业
How to differentiate between the different types of C++ specializations when writing/speaking
问:
我认为我对“专业化”含义的一些困惑在于,它似乎有两个相关但不同的含义。这是我似乎遇到的两个定义:
从模板实例化创建的用于处理一组特定模板参数的定义称为专用化。
这似乎意味着,如果我有一些模板化类:
template <typename T>
class Foo { ... };
例如,我通过简单地实例化来创建一个专业化。
这是有道理的,因为模板只是一个原型,编译器从中创建一个专门用于 .Foo
Foo<int>
int
但是,我也看到模板专业化指的是一个不同的概念。有时它似乎被称为完整模板专业化,而另一些则似乎被称为部分模板专业化。这似乎是为模板参数的子集指定单独的“专用”代码的行为。所以说我有一个非常人为的例子,我想为除 之外的所有类型返回一些值,在这种情况下,我想先将值除以 255。我可以这样写:getMagnitude()
uint8_t
template <typename T>
float getMagnitude(T value)
{
return static_cast<float>(value);
};
template <typename T>
float getMagniude<uint8_t>(T value)
{
return static_cast<float>(value)/255.f;
};
这样,我仍然有一个模板,但我可以专门化它,使其针对不同的模板参数采取不同的行为。这也解释了为什么它被称为专业化,因为它专门化某些模板参数的行为。getMagnitude()
不过,在网上和其他人交谈时,这个术语似乎并不总是很清楚(至少对我来说不是)。是那种仅从上下文中就应该清楚的事情吗?或者有没有办法在说/写文档时区分这两种类型的模板专业化?(此外,是否可能还有我不知道的其他类型的模板专业化?
答:
术语非常清晰和准确。实例化和专用化是不同的概念,可以是隐式的,也可以是显式的。
专用化是从模板化实体实例化 ([temp.inst]) 或模板化实体的显式专用化 ([temp.expl.spec]) 的类、变量、函数或类成员。
这就是您在 IBM 文档中引用的意思。实例化(显式或隐式)是生成专用化的一种方法。另一种方式是明确的专业化。请注意,在代码中找不到隐式专用化。相反,如有必要,它会在编译时生成(实例化需要)。
除非类模板专用化是声明的专用化,否则当在需要完全定义的对象类型的上下文中引用专用化时,或者当类类型的完整性影响程序的语义时,将隐式实例化类模板专用化。
实例化可以是隐式的(如在示例中使用时),上面的引文涵盖了这一点,也可以是显式的,下面的引文涵盖了这一点。Foo<int>
类、函数、变量或成员模板专用化可以从其模板显式实例化。 类模板的成员函数、成员类或静态数据成员可以从与其类模板关联的成员定义显式实例化。
例如:
template <typename T>
class Foo { ... };
template class Foo<int>; // explicit instantiation
同样,这不是一个显式的专用化,因此编译器会生成专用化本身。你不给它任何实现,它来自模板。
显式专用化 ([temp.expl.spec]
) 是您完整编写的内容。在带有 的(无效)示例中,它看起来像这样:getMagnitude
template <typename T>
float getMagnitude(T value)
{
return static_cast<float>(value);
};
template <> // no template parameter
float getMagnitude<uint8_t>(uint8_t value) // explicit types, no `T` anywhere
{
return static_cast<float>(value)/255.f;
};
这里,是函数模板的显式专用化。由您提供实现。getMagnitude<uint8_t>
getMagnitude
这也称为显式完整模板专用化,因为所有模板参数都具有类型或值。它不再是模板。
类也可以做同样的事情。但是,与函数不同,您也可以部分专用类。这称为类模板部分专用化。
类模板的部分专用化提供了模板的替代定义,当专用化中的参数与部分专用化 ([temp.class.spec.match]) 中给出的参数匹配时,将使用该模板代替主定义。
同样重要的是:
每个类模板部分专用化都是一个不同的模板,应为模板部分专用化 ([temp.class.spec.mfunc]) 的成员提供定义。
例:
template <typename T, typename U>
class Foo { ... };
template <typename V>
class Foo<V, V> { ... }; // partial specialization for when T and U are the same
请注意,部分专用化仍然是一个模板:它至少需要一个模板参数(在本例中,也可以用 )。typename V
V
T
上一个:C++ 阻止编译完整模板专项化
下一个:如何根据类型更改/设置模板参数?
评论
template <typename T> class Foo { int m; };
template <> class Foo<bool> { bool m; };
Foo<bool>
Foo