C++中与模板相关的语法元素的名称分类

Taxonomy of names for template-related syntactic elements in C++

本文关键字:语法 元素 分类 C++      更新时间:2023-10-16

我一直在仔细研究C++中的模板,我发现似乎没有一套既定的严格术语来清楚地识别和区分/消除使用模板时可能出现的每一个语法元素的歧义,这很有挑战性。

例如,Josuttis和Vandevoorde关于模板的书《C++模板:完整指南》(C++templates:The Complete Guide)是一本出色的书,但即使是这本书也没有明确指出涉及模板的每个语法元素的严格术语。相反,这些含义从上下文中是清晰的。

考虑下面这个简单的例子,我相信,它突出了涉及模板的11个不同的相关句法组件。

#include <iostream>
#include <vector>
template
<
typename 
M1, // <-- (1) "Primary template declaration template parameter
//          identifier"
typename M2 // ditto
> // <-- (2) (entire <...> syntactic element) "Primary template declaration
//                                           template parameter list"
class Foo
{
// <-- (3) "Primary class template definition"
};
template
<
typename
T1, // <-- (4) "Template specialization declaration template
//          parameter identifier"
typename A1, typename M2 // ditto
> // <-- (5) (entire <...> syntactic element) "Template specialization
//                                           declaration template
//                                           parameter list"
class Foo
<
std::vector<T1, A1> &, // <-- (6) "Template specialization
//          declaration TEMPLATE PARAMETER
//          SPECIALIZATION ARGUMENT"
//          (?)
M2
> // <-- (7) (entire <> syntactic element) "Template specialization
//                                        declaration TEMPLATE PARAMETER
//                                        SPECIALIZATION ARGUMENT LIST"
//                                        (?)
{
// <-- (8) "Template specialization class definition"
};
int main()
{
Foo
<
std::vector<int> &, // <-- (9) "Template class instantiation
//          template parameter"
//          (?) 
int // diito
> // <-- (10) (entire <> syntactic element) "Template class
//                                         instantiation template
//                                         parameter list"
//                                         (?)
f; // <-- (11) "Template class instantiation instance variable name"
}

在代码示例中,我指出了11个不同的与模板相关的语法元素,并为每个元素提供了严格的分类标签。

我怀疑我对这些元素中的大多数使用了正确的分类标识符(但如果我错了,请纠正我)。

然而,句法项(6)、(7)、(9)和(10)是棘手的——例如,在(6)和(7)的情况下,存在模板专业化的情况,其中一对尖括号<>出现两次,因此,对于这两对非常不同的尖括号,用于指示尖括号之间出现的参数(自变量?)的标识符必须有分类上的区别。模板实例化(9)和(10)涉及另一个使用尖括号,因此出现在这些括号内的参数也必须有自己的识别分类标识符。

也许,在这个问题上,我使用了适当严格的术语,但我想知道:

  1. 有没有比我使用的更简单、更严格的术语?

  2. 我是否在识别标签中使用了无关和/或不必要的词语?

  3. 我的识别标签中是否缺少单词?

  4. 我使用的识别标签是否正确?

我认为您不需要太关注模板参数,它们在任何地方都扮演着相同的角色。一些非常重要的术语,其中一些你没有提到:

template<typename T> struct foo;是主模板的声明
template<typename T> struct foo<T*>;是部分专门化的声明
template<> struct foo<int>;是一个显式专门化的声明。

当遇到类似变量定义foo<double> f;的情况时,有时需要实例化适当的专门化。特别是,如果声明了显式专门化,则不需要它。非正式地,隐式实例化的过程是对以下内容的重写:

template<typename T> struct foo {
void bar();
};
template<typename T> void foo<T>::bar() {}

到此:

template<typename T> struct foo;
template<> struct foo<double> {
void bar();
};
template<> void foo<double>::bar() {}

也可以在任何给定的TU中请求实例化,这被称为显式实例化:

// explicit instantiation declaration, C++11
extern template class foo<double>;
// explicit instantiation definition
template class foo<double>;
// can also instantiate a member of the template more specifically:
template void foo<double>::bar();

顾名思义,显式实例化定义是保证模板(如果适用,还包括其所有成员)被实例化的一种方式。显式实例化声明有点相反——它们抑制隐式实例化,而是使用由匹配的显式实例化定义生成的实例化。显式实例化功能的总体意图是为程序提供"指导"编译器的方法,例如帮助缩短编译时间。

我不会评论显式实例化的实现质量——事实上,请注意,显式实例化声明是最近添加的。我认为你可以花很多时间使用C++,而不会遇到或需要任何一个功能。

也许令人困惑的是,许多人实际上会非正式地使用"模板实例化"一词,而不是"模板专业化"。为了澄清,以下都是模板专业化:std::deque<int>std::less<T*>std::vector<bool>(当然不是同一类模板!)。并不是所有对模板专门化的使用或提及都会触发或引用模板实例化。我认为,不必知道何时或是否触发模板实例化是模板的一个方便特性。

事实上,有一种东西被称为实例化点:

// Declare template
template<typename T> struct foo;
// Use template and mention template specialization
// but no instantiation is required here!
typedef foo<int> F;
// Point of instantiation of foo<int>
// an actual definition of foo<int> is needed here
F f;

(虽然我在这里只使用了类模板,但我所描述的所有内容都适用于整个模板,包括函数模板。)