Reputation: 23634
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:
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?
What are placed in the global namespace
? Is it required to use the ::
when calling functions in global namespace
under all circumstances?
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!
Upvotes: 3
Views: 175
Reputation: 109119
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;
}
Upvotes: 1
Reputation: 21900
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;
Upvotes: 4