我正在学习C++中的模板。特别是,我读过POI。所以我尝试(通过阅读和写作(不同的例子。下面给出了一个我不清楚的例子:
template<typename T>
void g1(T p)
{
}
template<typename T>
void f1(T x)
{
g1(x); // #1: Is this point a POI for g1<T>(x)?
}
//#2: Or is this point a POI for g1<T>(x)?
//#3: Or is this point a POI for g1<T>(x)?
int main()
{
f1(7); // this point cannot be a POI
}
// #4 I know that this point 4 is a POI for f1<int>(int) but is this point also a POI for g<T>(x)?
在上面的片段中,我知道点#4
是f1<int>(int)
的POI。但是点#4
也是g1<T>(x)
的POI吗?我知道在语句g1(x);
中,名称g1
是一个不合格的依赖名称。我也知道POI
用于在包含该引用的最近的命名空间范围声明或定义。
这就是为什么点#4
是f<int>(int)
的POI。但是类似地,点#2
应该是g1(x);
的POI。但我不确定g1(x);
的POI在哪里。那么,对于像g1
这样的非限定从属名称,查找POI的规则是什么呢。
我的问题是:
点
#4
也是g1<T>(x)
的POI吗?如果是,那么为g1
这样的非限定从属名称查找POI的规则是什么。根据我引用的声明(来自C++模板:完整指南(,
#2
不应该是g1<T>(x);
的POI。我想这可以归结为语句g1(x);
是否引用了函数模板专门化。如果是,那么根据引用的声明,点#2
应该是g<T>(x);
的POI。我可能错了。如果我删除语句
f1(7);
,会发生什么变化。据我所知,这个翻译单元将不再有POI。但我不能百分之百肯定这一点。或者删除f1(7);
会使程序现在不成形。
函数模板的实例化点表面上很简单:它是编译器第一次看到具体函数的地方。
CCD_ 23是一个函数模板;它是一种基于模板参数生成函数族的编译器构造。g1<int>
是一个具体的函数,是编译器实例化模板g1
以生成真实函数的产物。
当编译器在f1
的定义中看到g1(x)
时,它会看到x
是一个类型依赖于模板参数的表达式。但是编译器还不知道模板参数是什么。所以它不知道g1(x)
会做什么。是的,它可以看到函数模板g1
,但由于x
在这一点上是未知的,它不知道它会传递给g1
什么模板参数。
因此,此时它无法实例化模板。只有当f1
本身被实例化时,它才能弄清楚如何实例化g1
到g1(x)
。
因此,C++将模板函数的实例化点推迟到编译器完全了解任何潜在模板参数的第一个地方。表达式g1(x)
只有在f1
的实例化发生时才有意义。因此,如果您所做的操作导致f1<int>
被实例化,那么g1<int>
将在同一点被实例化。