error: la llamada de 'max (int, int)' sobrecargada es ambigua

#include <iostream>

using namespace std;

template<typename T>
T max(T lhs, T rhs)
{
  return lhs < rhs ? rhs : lhs;
}
template<>
int max<int>(int lhs, int rhs)
{
  return lhs < rhs ? rhs : lhs;
}

int main()
{
  cout << max<int>(4, 5) << endl;

}

~/Documents/C++/boost $ g++ -o testSTL testSTL.cpp -Wall
testSTL.cpp: In function ‘int main()’:
testSTL.cpp:18:24: error: call of overloaded ‘max(int, int)’ is ambiguous
testSTL.cpp:11:5: note: candidates are: T max(T, T) [with T = int]
/usr/include/c++/4.5/bits/stl_algobase.h:209:5: note:                 const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]

¿Cómo corrijo este error?

preguntado el 01 de febrero de 12 a las 14:02

Eliminar el using namespace std; -

@Richard: Because English isn't the first language for many of us. -

@VJovic: That's no excuse. At the same time the rest of the English used was learned, the proper way to ask a question could have been. I don't understand where anyone, native English speaker or not, would get the idea that "how to correct this error" is magically a valid question construct. -

@RichardJ.RossIII: Not everybody on this site is a native english speaker and it can be difficult to sense the real meaning of an expression. At least the final goal is reached: you understood what he asked. :) -

I'd hazard a guess English isn't their first language - I wish I was that good at a foreign language, so I can't complain :p -

6 Respuestas

It's all because of your using namespace std;. Remove that line. By that using-directive, you bring std::max (which must be somehow included via iostream) into the global scope. Therefore the compiler doesn't know which max llamar - ::max or std::max.

I hope this example will be a good scarecrow for those who think that using directives come at no cost. Weird errors are one side effect.

Respondido 01 Feb 12, 18:02

It's worth noting ADL side-effects of not using them though. :-D Ex: no one writes std::cout.operator<<("hello world!").operator<<(std::endl); even though that is required for defined behavior without using declarations/directives, as ADL is not standardized across compilers. Sutter has a whole section on this on why using directives should be encouraged in C++ Coding Standards because of the undefined behaviors that result from inadvertently depending on ADL. - apestoso472

@stinky472: ADL is standard. Compilers not supporting it should be thrown away. - Armen Tsirunyan

@stinky472: Sutter has lots of sections in lots of books about why not do this or that, because while it is standard, msvc doesnt work properly with it. This is all driven by FUD and the pressure should be put on the compiler people to fix their stuff instead of programmers to use fugly workarounds. ADL works fine in the major open source compilers btw. - PlasmaHH

@LightnessRacesinOrbit: Of course not. ADL was invented primarily because of the issues with operators, so it's perfectly OK to rely on ADL. - Armen Tsirunyan

@stinky472: ADL rules are well-defined in the C++ standard and they are far less complicated than rules of, say, overload resolution or template point of intantiation. I think no relying on ADL is a bad practice, rather than the reverse - Armen Tsirunyan

I guess the compiler can't work out whether to use std::max or your max, because you've got a using namespace std; and both your max and the std::max fit the bill

Respondido 01 Feb 12, 18:02

You're colliding with std::max(). Rename it to something else like mymax y funcionará

Respondido 01 Feb 12, 18:02

Even better to not define it in std namespace, like Armen mentioned. - Error fatal

The OP never defined it in std namespace. I advised against bringing all the names of std namespace into the global scope - Armen Tsirunyan

The whole point of putting the standard library in std namespace is so you can define your own max function in some other namespace (or globally), or in general, don't have to constantly think which names are used in the standard (or any other) library. What's the point of namespaces in the first place, if you don't employ them to resolve naming collisions and keep doing with prefixes instead?! - Unclebens

You have both your max y la std::max. The compiler doesn't know which one you intended to call.

You can tell it by calling ::max(4,5) or std::max(4,5), or - even better - not have using namespace std en el archivo.

Respondido 01 Feb 12, 18:02

That's because there's already std::max template function defined. Remove the 'using namespace std' and add 'std::' where needed., or use '::max'.

Respondido 01 Feb 12, 18:02

The problem is that there is already a function named 'max' defined by std. To fix this, rename your function to something else, like this:

#include <iostream>

using namespace std;

template<typename T>
T mymax(T lhs, T rhs)
{
    return lhs < rhs ? rhs : lhs;
}
template<>
int mymax<int>(int lhs, int rhs)
{
    return lhs < rhs ? rhs : lhs;
}

int main()
{
    cout << mymax<int>(4, 5) << endl;

    return 0;
}

Respondido 01 Feb 12, 18:02

Y deja de usar using namespace std - Carreras de ligereza en órbita

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.