功能模板:为什么会产生歧义?

时间:2013-03-31 02:09:06

标签: c++ templates

我有以下简单的功能模板:

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>]   

我的问题如下:

  1. 在这种情况下,编译器是否默认搜索std命名空间,即使我没有包含<algorithm>所在的头文件std::max

  2. global namespace中放置了哪些内容?在所有情况下调用::中的函数时是否需要使用global namespace

  3. 为什么在maxinteger类型上应用float时没有歧义,string类型只有歧义?

  4. 仅供参考:我正在使用gcc 4.5.3进行编译。 谢谢!

2 个答案:

答案 0 :(得分:4)

  

在这种情况下,编译器默认搜索std命名空间   即使我没有包含std :: max所在的头文件   位于?

是的,这称为Argument Dependent Lookup。请注意,定义std::max的头文件可能包含在您包含的某个文件中。

  

全局命名空间中放置了什么?是否需要使用::   在所有情况下调用全局命名空间中的函数?

不,只有在有歧义时才会这样。这是其中一种情况。

  

为什么在对整数和浮点数应用max时没有歧义   类型,只对字符串类型有歧义吗?

因为intfloat都未在命名空间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;
}