我有以下简单的功能模板:
max.hpp:
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a <b? b :a;
}
max.cpp
#include <iostream>
#include <string>
#include "max.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): "<< ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
std::cin.get();
return 0;
}
这很好用,因为::
会告诉编译器在全局命名空间中搜索max
模板。但是,当我在这3个案例中删除::
时,我收到以下歧义错误消息:
max.cpp: In function ‘int main()’:
max.cpp:21:43: error: call of overloaded ‘max(std::string&, std::string&)’ is ambiguous
max.hpp:2:17: note: candidates are: const T& max(const T&, const T&)
[with T = std::basic_string<char>]
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stl_algobase.h:209:5:
note: const _Tp& std::max(const _Tp&, const _Tp&)
[with _Tp = std::basic_string<char>]
我的问题如下:
在这种情况下,编译器是否默认搜索std
命名空间,即使我没有包含<algorithm>
所在的头文件std::max
?
global namespace
中放置了哪些内容?在所有情况下调用::
中的函数时是否需要使用global namespace
?
为什么在max
和integer
类型上应用float
时没有歧义,string
类型只有歧义?
仅供参考:我正在使用gcc 4.5.3进行编译。 谢谢!
答案 0 :(得分:4)
在这种情况下,编译器默认搜索std命名空间 即使我没有包含std :: max所在的头文件 位于?
是的,这称为Argument Dependent Lookup。请注意,定义std::max
的头文件可能包含在您包含的某个文件中。
全局命名空间中放置了什么?是否需要使用:: 在所有情况下调用全局命名空间中的函数?
不,只有在有歧义时才会这样。这是其中一种情况。
为什么在对整数和浮点数应用max时没有歧义 类型,只对字符串类型有歧义吗?
因为int
和float
都未在命名空间std
中定义。因此,编译器不会查看该命名空间,因此在重载解析期间不会考虑std::max
。这不是std::string
的情况。
请注意,如果您这样做,可能会触发相同的歧义:
using namespace std;
或者:
using std::max;
答案 1 :(得分:1)
另一个answer解释了为什么由于ADL而出现歧义。避免它的一种方法是将调用限定为max
(在这种情况下使用::
将名称查找限制为全局命名空间。)
限制ADL的另一种可能更为模糊的方法是使用以下语法
std::cout << "max(s1,s2): " << (max)(s1,s2) << std::endl;
// ^ ^
以下示例compiles没有错误:
#include <iostream>
#include <string>
#include <algorithm>
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
int main()
{
std::string s1("mathematics");
std::string s2("math");
std::cout << "max(s1,s2): " << (max)(s1,s2) << std::endl;
}