C ++语言标准规定了标准库中有关模板组件的以下内容:
效果未定义...如果在实例化模板组件时将不完整类型用作模板参数,除非特别允许该组件(C ++11§17.6.4.8/ 2)。
以下是否会导致std::vector
类模板的实例化?
class X;
std::vector<X> f(); // Declaration only; we will define it when X is complete
另一种方式是,在函数声明std::vector<X> f();
中,std::vector
是否使用参数X
进行实例化?或者,std::vector<X>
是否在f()
使用或定义之前未实例化?
同样,以下是否会导致std::vector
类模板的实例化?
class X;
typedef std::vector<X> XVector; // We will complete X before we use XVector
虽然我在这些示例中使用std::vector
,但问题同样适用于所有模板。
答案 0 :(得分:5)
§14.7.1\ 1隐式实例化[temp.inst]
除非已明确表示类模板特化 实例化(14.7.2)或明确专门化(14.7.3),类 模板特化是在隐式实例化的时候 在需要a的上下文中引用特化 完全定义的对象类型或类的完整性 type影响程序的语义。隐式实例化 类模板专门化导致隐式实例化 声明,但不是定义或默认参数, 类成员函数,成员类,静态数据成员和 会员模板;它导致隐式实例化 成员匿名联盟的定义。除非是班级成员 模板或成员模板已显式实例化或 明确专门化,成员的专业化是隐含的 在上下文中引用特化时实例化 要求成员定义存在; 特别是 静态数据的初始化(以及任何相关的副作用) 除非静态数据成员本身在其中使用,否则不会发生成员 一种需要静态数据成员定义的方法。
§8.3.5\ 9函数[dcl.fct]
不应在返回或参数类型中定义类型。的类型 函数定义的参数或返回类型不应为 不完整的类类型(可能是cv-qualified)除非函数 definition嵌套在该类的member-specification中 (包括在类中定义的嵌套类中的定义)。
§3.1\ 2声明和定义[basic.def]
声明是一个定义,除非声明没有的函数 指定函数的主体(8.4),它包含extern说明符 (7.1.1)或连接规范25(7.5),既不是初始化程序 也不是函数体,它在类中声明了一个静态数据成员 定义(9.4),它是一个类名声明(9.1),它是一个 opaque-enum-declaration(7.2),或者是typedef声明(7.1.3), 一个using-declaration(7.3.3),一个static_assert-declaration(第7条), 属性声明(第7条),空声明(第7条), 或使用指令(7.3.4)。
只有在需要时才会实例化。我无法在任何地方找到明确的定义,但第二句话说这些声明不是定义,对我来说似乎是相同的。
答案 1 :(得分:2)
不,它不会实例化模板。 Mooing Duck的答案提供了所有必要的引用,但这里有一些分析。
默认情况下,如果不存在要求完全定义的类型(第14.7.1 / 1节),则不会发生实例化。函数定义特别需要完整的类型(第8.3.5 / 9节),但问题是标准的其他部分是否也要求其他声明。
但是定义有一个特殊的例外,它揭示了非定义声明确实不同:
函数定义的参数类型或返回类型不应是不完整的类类型(可能是cv限定的),除非函数定义嵌套在该类的成员规范中(包括定义的嵌套类中的定义)在课堂内)。
成员规范中的函数定义有什么特别之处?因为成员规范不能两次声明相同的函数(§9.2/ 1),并且在所有成员声明(§3.3.7/ 1.1)之后处理成员函数体。本质上,嵌套的成员函数定义在第一次传递期间被视为声明,然后在处理完整个成员规范之后被定义为一个定义,并且该类已完成(第9.2 / 2节)。并且§8.3.5/ 9规定第一次通过允许不完整的类,但不允许第二次通过。
对标准的函数声明和实例化规则进行详尽,明确的搜索是非常繁琐的。但是这个例子虽然仅限于成员函数和封闭类型的完整性,但可以合理地扩展到其他函数和类型。无论如何,这是一个很好的证据。