在 Linux 中我得到
template max() is called
但是在 Windows 下我得到了
non-template max() is called
为什么?在 Linux 中,我使用 gcc 4.5,在 Windows 中,我使用 VS2008。
#include <iostream>
#include <vector>
template < typename T >
inline void max( const int& a, const T& b )
{
std::cout << "template max() is called" << std::endl;
}
template < typename T >
inline void Imax( const int& a, const std::vector<T>& b)
{
max(a, b[0]);
}
inline void max( const int& a, const int& b )
{
std::cout << "non-template max() is called" << std::endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
Imax(1, v);
return 0;
}
最佳答案
在准标准 C++ 中,您可能会得到非模板 max
。
(没有标准,很难说您应该得到什么,但是所有
我知道的准标准编译器会将名称查找推迟到
实例化。)从 C++89 开始,你应该得到模板 max
;名称查询
发生在两个阶段:定义模板时(此时,仅
模板 max
是可见的),当模板被实例化时,
但在实例化点,仅用于相关名称,并且仅使用
日常事件。在您的代码中,max
是从属名称,但符号
触发 ADL 的是 std::vector
(在 std
中绘制)和 int
,它
不添加任何东西,甚至不添加全局命名空间。所以
未找到非模板 max
。
这些规则是 C++ 委员会最后正式制定的规则之一,并且 编译器不可能一夜之间改变,所以实际上,如果 编译器可以追溯到 1995 年之前的任何时候,您可能会期望 前标准行为。对于以后的任何事情,我倾向于将其视为 编译器错误,但是......编译器必须支持现有代码,并且 理想情况下,以后的编译器将可以选择使用以前的名称 查找规则。 (我说理想情况下,因为有两套不兼容的 名称查找规则绝对不重要。刚入手一套 对于大多数编译器实现者来说,正确已经足够困难了。)
众所周知,Microsoft 的模板实现 即使在今天也不符合标准。
关于c++ - 模板函数和非模板函数的调用顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12174493/