C++语言标准规定了关于标准库中的模板组件的以下内容:
在实例化模板组件时,除非特别允许该组件使用不完整的类型作为模板参数,否则效果是undefined...if (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
,但这个问题同样适用于所有模板。
发布于 2011-10-12 03:02:05
§14.7.1\1隐式实例化temp.inst
除非类模板专门化已经显式实例化(14.7.2)或显式专门化(14.7.3),否则当在需要完全定义的对象类型的上下文中引用专门化时,或者当类类型的完整性影响程序的语义时,类模板专门化被隐式实例化。类模板专门化的隐式实例化导致类成员函数、成员类、静态数据成员和成员模板的声明的隐式实例化,而不是定义或默认参数的隐式实例化;并且它导致成员匿名联合的定义的隐式实例化。除非类模板或成员模板的成员已显式实例化或显式专门化,否则当在要求成员定义存在的上下文中引用专门化时,成员的专门化是隐式实例化的;具体地说,除非静态数据成员本身的使用方式要求静态数据成员的定义存在,否则不会发生静态数据成员的初始化(以及任何相关的副作用)。
§8.3.5\9函数dcl.fct
不应在返回或参数类型中定义
类型。函数成员定义的参数类型或返回类型不应是不完整的类类型(可能是cv限定的),除非函数定义嵌套在该类的成员规范中(包括类中定义的嵌套类中的定义)。
§3.1\2声明和定义basic.def
声明是一个定义,除非它声明一个函数而不指定函数体(8.4),它包含外部说明符(7.1.1)或链接规范25 (7.5),并且既不是初始化器也不是函数体,它在类定义中声明静态数据成员(9.4),它是类名声明(9.1),它是不透明枚举声明(7.2),或它是类型定义声明(7.1.3),使用声明(7.3.3)、 _assert声明(第7条)、属性声明(第7条)、空声明(第7条)或使用指令(7.3.4)。
只有在需要时才会实例化它。我在任何地方都找不到明确的定义,但第二句话说这些声明不是定义,这对我来说似乎是一样的。
发布于 2012-02-05 18:12:21
不,它不会实例化模板。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规定,第一次传递允许不完整的类,但第二次不允许。
对标准的函数声明和实例化规则进行详尽、明确的搜索是相当繁重的。但是,这个示例虽然仅限于成员函数和封闭类型的完整性,但也可以合理地扩展到其他函数和类型。无论如何,这都是一个很好的区分证据。
https://stackoverflow.com/questions/7730874
复制相似问题