3

I have the following simple function template:

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;
}

This works fine, since :: will tell compiler to search for max template in global namespace. However, when I remove those :: in those 3 cases, I got the following ambiguity error message:

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

My questions are as follows:

  1. In this case, does the compiler search for std namespace by default even I did not include the header file <algorithm> where std::max is located?

  2. What are placed in the global namespace? Is it required to use the :: when calling functions in global namespace under all circumstances?

  3. Why there is no ambiguity when max is applied on integer and float type, only has ambiguity for string type?

FYI: I am using gcc 4.5.3 for compiling. Thank you!

4

2 回答 2

4

In this case, does the compiler search for std namespace by default even I did not include the header file where std::max is located?

Yes, this is called Argument Dependent Lookup. Note that the header file in which std::max is defined might be included by some file you included.

What are placed in the global namespace? Is it required to use the :: when calling functions in global namespace under all circumstances?

No, only when there's ambiguity. This is one of those cases.

Why there is no ambiguity when max is applied on integer and float type, only has ambiguity for string type?

Because neither int nor float are defined in namespace std. Therefore the compiler does not look inside that namespace and as a consequence std::max is not considered during overload resolution. This is not the case of std::string.

Note that you could trigger the same ambiguity if you did:

using namespace std;

Or:

using std::max;
于 2013-03-31T02:39:14.440 回答
1

The other answer explains why the ambiguity arises because of ADL. One way to avoid it is to qualify the call to max (in this case using :: to restrict the name lookup to the global namespace).

Another, perhaps more obscure, method to restrict ADL is to use the following syntax

std::cout << "max(s1,s2): " << (max)(s1,s2) << std::endl; 
//                             ^   ^

The following example compiles without errors:

#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;
}
于 2013-04-04T17:51:29.347 回答