user5028722
user5028722

Reputation:

Why Template Function call is ambiguous?

#include <iostream>
using namespace std;
template <typename T>
T max(T x, T y)
{
    return (x > y) ? x : y;
}
int main()
{
    cout << max(3, 7) << std::endl;
    cout << max(3.0, 7.0) << std::endl;
    cout << max(3, 7.0) << std::endl;
    return 0;
}

I'm Expecting max's Instance here

cout << max(3, 7) << std::endl; // max (int, int)
cout << max(3.0, 7.0) << std::endl; // max (double, double)
cout << max(3, 7.0) << std::endl; // max(int, double)

Then what is the problem ? Why I'm getting

11 25 [Error] call of overloaded 'max(double, double)' is ambiguous

Upvotes: 2

Views: 3759

Answers (3)

Loveforcode
Loveforcode

Reputation: 1

Max is a library function.just change the max identifier for your function to max1 or any other name that is not a function defined any header files. That should solve your problem.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206747

The line

using namespace std;

makes things complicated, for sure. However, even after you remove that line, the problem continues to exist.

The call max(3, 7.0) can be resolved to max<int> or max<double>. To resolve to max<int> a double has to be converted to an int. To resolve to max<double>, an int has to be converted to a double. Since both require a conversion and one conversion cannot be given higher priority than the other, the compiler is not able to resolve which one to use.

You'll have to be explicit which version of max you want to use.

max<int>(3, 7.0) will convert 7.0, a double, to an int.

max<double>(3, 7.0) will convert 3, an int, to a double.

Upvotes: 2

Barry
Barry

Reputation: 304152

If you view the compile error in full, you'd see why. Here's what gcc 5.2 gives me:

main.cpp: In function 'int main()':
main.cpp:10:21: error: call of overloaded 'max(int, int)' is ambiguous
     cout << max(3, 7) << std::endl;
                     ^
main.cpp:4:3: note: candidate: T max(T, T) [with T = int]
 T max(T x, T y)
   ^
In file included from /usr/local/include/c++/5.2.0/bits/char_traits.h:39:0,
                 from /usr/local/include/c++/5.2.0/ios:40,
                 from /usr/local/include/c++/5.2.0/ostream:38,
                 from /usr/local/include/c++/5.2.0/iostream:39,
                 from main.cpp:1:
/usr/local/include/c++/5.2.0/bits/stl_algobase.h:219:5: note: candidate: constexpr const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
     max(const _Tp& __a, const _Tp& __b)
     ^

Basically, there are two max functions - yours and std::max, which is included by some chain of other #includes from <iostream>. The latter is found by lookup because of your

using namespace std;

Effectively, we have:

template <typename T> T max(T, T);                      // yours
template <typename T> T const& max(T const&, T const&); // std

Neither is better than the other, hence ambiguous. This is a great reason to avoid using namespace std. Or a great reason to not reinvent the wheel when it comes to standard library functions - just use std::max. Or both.


On the other hand, this one

max(3, 7.0)

will fail regardless as a template deduction failure. It would deduce T as int for the first argument, and T as double for the second - but there can only be one T! You would have to explicitly call either max<int>(3, 7.0) or max<double>(3, 7.0) to get around the deduction failure, depending on which of the two arguments you want to cast.

Upvotes: 6

Related Questions