Why is this call ambiguous?

1
2
3
4
5
6
7
8
9
10
namespace A{
template <typename T> T const& max(T const& one, T const& two) {
    return two<one?one:two;
}}


int main() {
    using A::max;
    std::cout << max(std::string("34"),std::string("454")) ;
}
Looks like VS is confusing A::max and std::max, although I don't know why std::max would be a candidate since you're not using it.

This is indeed very strange.
closed account (zb0S216C)
Try removing using A::max and use the scope resolution operator on max. Also, In Visual C++ Express '10, the compiler complains about passing string literals instead of string objects. Also, the compiler doesn't like the fact that you aren't using c_str( ) when printing the result of max( )( due to you passing string literals ). However, when you pass string literals, your cannot return a object, because no string objects were passed.

Also, I don't understand why you're comparing strings that way.

Wazzak
Last edited on
Won't that just compare the ASCII values of the two strings?
In MSVC at least - the issue the OP is seeing is down to the inclusion of <string>

std::string is defined in the xstring header file, which includes <xmemory> which includes <xutility>.
<xutility> throws a couple of min and max template functions into the std:: namespace.
I found the answer. Whenever you call a function, the C++ compiler looks for in the namespace you would expect (A here) but also in the namespaces of the arguments of the functions (std here). std has a max function so that is where conflict stems from.
It's called ADL -- Argument Dependent Lookup, also referred to as "Koenig Lookup".

Since you are passing std::strings to the function, ADL will consider the std namespace (because that's where string is declared). But it will also consider A since you explicitly told it to.
Learn something new every day. I wasn't aware of this.

Since you are passing std::strings to the function, ADL will consider the std namespace (because that's where string is declared).


That seems incredibly strange and counter intuitive to me. I wonder why they decided to make it work that way.
The made it work this way so that the following compiles.

1
2
3
4
5
6
7
#include<iostream>
 
int main() 
{
  std::cout << "Hello World, where did operator<<() come from?" << std::endl;
  return 0;
}

Useful link -> http://en.wikipedia.org/wiki/Argument-dependent_name_lookup
@Disch:

The thought is that the functions that operate on a given type would be declared inside the same namespace as the type itself is declared.
ah, yeah, that makes sense @ m4ster r0shi. I guess I never though about it that way.
Topic archived. No new replies allowed.