C++ 模板中的名称解析
我正在阅读有关模板名称解析的内容。只是为了体验一下我复制的代码,如下所示:C++ 模板中的名称解析,c++,templates,C++,Templates,我正在阅读有关模板名称解析的内容。只是为了体验一下我复制的代码,如下所示: void f (char c) { std::cout<<"f(char)\n"; } template <class T> void g(T t) { f(1); f(T(1)); f(t); d++; } double d; void f(int n) { std::cout<<"f(int)\n"; } void test()
void f (char c)
{
std::cout<<"f(char)\n";
}
template <class T>
void g(T t)
{
f(1);
f(T(1));
f(t);
d++;
}
double d;
void f(int n)
{
std::cout<<"f(int)\n";
}
void test()
{
std::cout<<"First call\n";
g(1);
std::cout<<"Second call\n";
g('a');
}
int main()
{
test();
return 0;
}
void f(字符c)
{
std::cout关于是否应该编译d++
的文章是正确的
Visual C++不做两阶段模板实例化-它几乎在解析时都进行解析。
Gcc和将给出正确的错误,并调用正确的f
关于是否应编译d++
的文章是正确的
Visual C++不做两阶段模板实例化-它几乎在解析时都进行解析。
GCC并将给出正确的错误,并将调用正确的<代码> f>代码> ,尽管VS2008被认为是它的时间标准最符合标准的C++编译器,这里我们有一个实例接受无效代码。G++不编译这个(D++:错误:D)在这个范围内没有声明)也就是说,任何依赖于C++语言复杂程度的程序都被破坏了:尽管VS2008被认为是它的时间标准最符合标准的C++编译器,但这里有一个实例接受无效代码。G++不编译这个(d++:错误:d)在这个范围内没有声明)也就是说,任何依赖C++语言复杂化的程序都被破坏了:
同样对于g(1)的第一个调用,我应该有一个f(char)调用,然后是两个f(int)调用,对于第二个调用,我应该有三个f(char)调用
对于符合标准的编译器,这不是预期的结果。因为两次使用基本类型调用它时,都不会在函数调用的实例化上下文中获得名称查找
实例化上下文中的名称查找仅适用于参数相关的查找(使用关联的名称空间称为查找)。int
和char
都没有参数相关的查找,因此在删除d++
行后,您执行的所有函数调用都将调用f(char)
因为我知道你不可能仅仅相信我,这里是标准的引用,出自14.6.4.2
:
对于依赖于模板参数的函数调用,如果函数名是非限定id而不是模板id,则使用常用的查找规则(3.4.1、3.4.2)查找候选函数,但以下情况除外:
- 对于使用非限定名称查找(3.4.1)的查找部分,只能找到具有来自模板定义上下文的外部链接的函数声明
- 对于使用关联名称空间(3.4.2)的查找部分,仅在模板定义上下文或模板实例化上下文中找到具有外部链接的函数声明
请注意,本文使用了本标准的一个有缺陷的示例(见14.6/9
)(请注意示例是非规范性的:它们不能更改或说明规则。它们的目的完全是说明性的)。该缺陷已修复,并已纳入即将发布的标准中。请参阅
如您所见,您必须从int
/char
更改为某些用户定义的类型(枚举或类),也可以在实例化上下文中查看查找的效果。有关详细信息,请阅读此答案
同样对于g(1)的第一个调用,我应该有一个f(char)调用,然后是两个f(int)调用,对于第二个调用,我应该有三个f(char)调用
对于符合标准的编译器,这不是预期的结果。因为两次使用基本类型调用它时,都不会在函数调用的实例化上下文中获得名称查找
实例化上下文中的名称查找仅适用于参数相关的查找(使用关联的名称空间称为查找)。int
和char
都没有参数相关的查找,因此在删除d++
行后,您执行的所有函数调用都将调用f(char)
因为我知道你不可能仅仅相信我,这里是标准的引用,出自14.6.4.2
:
对于依赖于模板参数的函数调用,如果函数名是非限定id而不是模板id,则使用常用的查找规则(3.4.1、3.4.2)查找候选函数,但以下情况除外:
- 对于使用非限定名称查找(3.4.1)的查找部分,只能找到具有来自模板定义上下文的外部链接的函数声明
- 对于使用关联名称空间(3.4.2)的查找部分,仅在模板定义上下文或模板实例化上下文中找到具有外部链接的函数声明
请注意,本文使用了本标准的一个有缺陷的示例(见14.6/9
)(请注意示例是非规范性的:它们不能更改或说明规则。它们的目的完全是说明性的)。该缺陷已修复,并已纳入即将发布的标准中。请参阅
如您所见,您将不得不从int
/char
更改为某些用户定义的类型(枚举或类),也可以在实例化上下文中查看查找的效果。阅读此答案了解更多信息。VS应该抱怨d++,因为应该在定义点查找d
文章不正确,调用应该解析为f(char),因为不应该对基本类型进行实例化点查找(参见tlib答案)
g++行为取决于版本:
- 在3.4之前,它总是进行实例化点查找,这是一个bug
- 从3.4开始,它会查找d的定义点;但它会查找定义点
基本类型作为模板参数时的实例化查找
是