#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]
How do I correct this error?
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 to call - ::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.
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
You're colliding with std::max(). Rename it to something else like mymax and it will work.
You have both your max and 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 in the file.
That's because there's already std::max template function defined.
Remove the 'using namespace std' and add 'std::' where needed., or use '::max'.
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;
}
Related
I was trying out a sample generic function in C++ , the code follows:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
template <typename T>
T max(T a, T b){
return (a>b)?a:b;
}
int main()
{
int a=2,b=4;
float af = 2.01,bf=2.012;
double ad = 2.11,bd=1.22;
cout<<max(a,b);
}
I am getting the error as
main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^main.cpp: In function ‘int main()’:
main.cpp:20:18: error: call of overloaded ‘max(int&, int&)’ is ambiguous
cout<<max(a,b);
^
main.cpp:20:18: note: candidates are:
main.cpp:9:3: note: T max(T, T) [with T = int]
T max(T a, T b){
^
What am I doing wrong here ?
What is meant by call of overloaded max(int&, int&) is ambiguous ?
Why am I getting its argument shown as & where as there was no such syntax defined by me above ?
The problem is that C++ already has a std::max definition.
Pick another name and everything should be fine.
In C++ the using namespace std approach is a bad idea as thousands of names will be injected. Just get the habit of typing std:: in front of standard names.
Remember also that saving time when writing is not really that important, what is important is saving time when reading (normally code is written just once but read and understood many times).
std:: in front of standard names actually speeds up reading and lets understanding on the spot that what is being used is part of the standard library (not everyone knows the whole standard library by heart).
Skypjack and 6502's answers are spot on so I won't go over that here.
It is also worth noting that the standard's version of max is not that clever. You can cause it not to compile with code like this:
int main()
{
int a = 0;
double b = 1;
auto c = std::max(a, b);
}
yields error message:
16 : error: no matching function for call to 'max(int&, double&)'
If we wanted to rewrite max, we might imagine that we were improving it by writing it this way:
#include <type_traits>
namespace notstd {
template <typename T1, class T2>
auto max_any(T1 a, T2 b) -> std::common_type_t<T1, T2>
{
return (a>b) ? a : b;
}
}
int main()
{
int a = 0;
double b = 1;
auto c = notstd::max_any(a, b);
}
But of course there would be some consequences.
Firstly, max_any is now forced to take copies and (possibly) perform conversions. For integers and doubles this is almost not worth mentioning.
But if T1 and T2 were two classes of object that had appropriate conversion operators, calling max_any on them could potentially be an expensive operation. It might also have material side-effects.
For this reason, std::max is defined in terms of arguments of type T&. It forces the caller to perform the conversion. It turns out that this is not a limitation of std::max. It is a safety feature.
The function does not inject any hidden side-effects into your code.
In order to maintain 'the path of least surprise' in its behaviour, the standard library sometimes requires that its users spell out the surprising behaviour that they want.
Example of surprising behaviour
This program will compile perfectly:
#include <cstdlib>
#include <iostream>
namespace notstd {
template <typename T1, class T2>
auto max_any(T1 a, T2 b)
{
return (b < a) ? a : b;
}
}
struct A {
A() = default;
};
struct B {
B() = default;
B (A const&) { std::exit(100); }
};
bool operator<(B const&, A const &) { return true; }
int main()
{
A a;
B b;
auto c = notstd::max_any(a, b);
std::cout << "Hello, World\n";
}
But it will never print "Hello, World".
Someone maintaining this code might be surprised to learn that.
There exists already a max function in the standard template library (namely std::max).
Using the using namespace directive, you are importing the names from the std:: namespace to the one in which you are using the declaration itself.
You can still use the following line to pick your implementation of max:
cout << ::max(a,b);
Otherwise, as someone already mentioned, you can choose a different name for your function or use directly the one fron the standard template library.
#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]
How do I correct this error?
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 to call - ::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.
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
You're colliding with std::max(). Rename it to something else like mymax and it will work.
You have both your max and 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 in the file.
That's because there's already std::max template function defined.
Remove the 'using namespace std' and add 'std::' where needed., or use '::max'.
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;
}
I have a question with the code below. When I compile it it complains with this error below. Now my question is if I remove the "const" in the declaration and change it to only :
template<class T> T max( T& left, T& right);
it becomes okay and the compiles/executes correctly. How come the compiler thinks that the call is ambiguous? Shouldn't the forward declaration follow the implementation?
==== start of error message====
max.cpp:10:34: error: call of overloaded ‘max(int, int)’ is ambiguous
max.cpp:10:34: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = int]
/usr/include/c++/4.6/bits/stl_algobase.h:210:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
max.cpp:11:44: error: call of overloaded ‘max(double, double)’ is ambiguous
max.cpp:11:44: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = double]
=======end of error message===
=============code starts here======
#include<iostream>
using namespace std;
template<class T> T max(const T& left, const T& right);
int main(void)
{
cout<<"max int:"<< max(1,4)<<endl;
cout<<"max double:"<< max(5.02,1.002)<<endl;
}
template<class T>
T max(const T& left, const T& right)
{
return left > right? left:right;
}
You have to do:
cout<<"max int:"<< ::max(1,4)<<endl;
cout<<"max double:"<< ::max(5.02,1.002)<<endl;
Since there is another max defined in std namespace. You have to inform the compiler to use the max defined in global namespace, which is the one you defined. See a live example here: Function template Demo
If you look at the std::max defined in std namespace:
template <class T> const T& max (const T& a, const T& b);
which returns const reference and takes const reference to parameters, that's why when you remove const, it will compile. Hope that this helps.
The std namespace has a max already built in, so you can either not have the line using namespace std; or put the max function in your own namespace.
namespace myNamespace {
//your max function
}
We have few functions already defined in std namespace like max(), swap() qsort(). So when you define your own function
max(const T& left,const T& right)
it is same as one in std namespace hence the error. So you can do following to make it work
call your function using scope resolution operator ::max(x,y)
remove const qualifier from your function
As others have written the compiler has found a max function additionally in namespace std. Now it tries to get the best version for you via function overloading. As both signatures are eaqual it can not choose a best version and complains. Now if you remove const the compiler can not bind a integer (or double) literal to a non const refference. Now it has only one choice and takes std::max functionality. You can see it with the following example:
#include <iostream>
namespace ns1 {
template<class T>
void doit(T const&) {
std::cout << "ns1::doit" << std::endl;
}
}
template<class T>
void doit(T&) {
std::cout << "::doit" << std::endl;
}
int main() {
using namespace ns1;
int i=1;
int const j=1;
doit(1);
doit(i);
doit(i+1-1);
doit(j);
return 0;
}
As everithing is an int the compiler has to choose a non const reference only if it has a non const variable (i). In other cases it choose the cont reference version from namespace ns1. It could even bind temporaries to const references (i+1-1).The same happens with your max and std::max.
Edit:
I forgott to say if you remove the const in your declaration the compiler choose std::max which is of course correct but not yours.
Can anyone tell me the cause of error ?
Error is
C:\web\template1.cpp||In function 'int main()':|
C:\web\template1.cpp|23|error: call of overloaded 'swap(int&, int&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = int]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = int]|
C:\web\template1.cpp|24|error: call of overloaded 'swap(double&, double&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = double]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = double]|
C:\web\template1.cpp|25|error: call of overloaded 'swap(char&, char&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = char]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = char]|
||=== Build finished: 3 errors, 0 warnings ===|
#include <iostream>
using namespace std;
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
swap(i,j);
swap(x,y);
swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}
Your swap conflicts with std::swap. Remove using namespace std; above and correct the rest code from std namespace.
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
Also it's worth reading Why is "using namespace std" considered bad practice?
Rename swap() as swap2() or the like. Or, better, never issue using namespace std;.
As written, your code introduces std::swap() through iostream, then dumps it atop your own swap() by using namespace.
There is already a swap function declared somewhere in your code. Change the function's name or remove the declaration of the other swap function.
This ambiguous errors occur due to using std functions as general functions.
There are two ways to overcome this.
1) Instead of declaring using namespace std; use std::cout
whenever you need to print any and std::endl for new line.
#include <iostream>
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
swap(i,j);
swap(x,y);
swap(a,b);
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
return 0;
}
2) You can also change the swap to Swap to not conflict with the inbuilt std::swap function.
#include <iostream>
using namespace std;
template <typename X>
void Swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
Swap(i,j);
Swap(x,y);
Swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}
#include <functional>
#include <iostream>
struct A {
friend bool operator==( const A & a, const A & b ){
return true;
}
};
namespace {
bool operator!=( const A &a, const A & b){
return !(a==b);
}
}
int main(int argc, char **argv) {
std::not_equal_to<A> neq;
A a;
bool test = neq(a, a);
return test ? 0 : 1;
}
This fails on CC (SunOs Compiler) with:
Error: The operation "const A != const A" is illegal.
"tempcc.cpp", line 16: Where: While instantiating "std::not_equal_to<A>::operator()(const A&, const A&) const".
"tempcc.cpp", line 16: Where: Instantiated from non-template code.
And on g++ with:
/usr/local/include/c++/3.3.2/bits/stl_function.h: In member function `bool std::not_equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]':
tempcc.cpp:16: instantiated from here
/usr/local/include/c++/3.3.2/bits/stl_function.h:183: error: no match for 'operator!=' in '__x != __y'
However if I remove the line #include <iostream> it compiles and runs just fine. Anyone dare to explain this?
According to Comeau, this isn't legal either way - the fact that the compiler builds it when you don't #include <iostream> may be the actual bug, not the other way around (or at least a disagreement in interpretation):
"stl_function.h", line 99: error: no operator "!=" matches these operands
operand types are: const A != const A
bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
^
detected during instantiation of "bool
std::not_equal_to<_Tp>::operator()(const _Tp &, const _Tp
&) const [with _Tp=A]" at line 19 of "ComeauTest.c"
"ComeauTest.c", line 10: warning: function "<unnamed>::operator!=" was declared but
never referenced
bool operator!=( const A &a, const A & b){
^
It makes sense that this doesn't build - placing operator!= in an unnamed namespace still puts it in a different namespace than ::, and I'm not entirely sure why g++ builds it without the iostream include - if you look at the preprocessor output from g++ it hasn't done anything hinky to reorder code or any such nonsense, and of course iostream doesn't define operator!= for A.
I do not have my copy of the C++ standard handy, but this link from IBM at least validates the claim that unnamed namespaces don't mix that well with the global one, explaining why you can't find the operator!= you've defined.
You also might find some helpful information in Anonymous Namespace Ambiguity.
The problem is that <functional> also pulls in several templates from from tuple and utility that interfere with the lookup.
If you were to remove this, e.g. by only including <bits/stl_function.h> in GCC, then there is no problem, although is is of course not a real solution. I suppose you cannot get around either implementing your own operator!=() or adding an explicit specialization for std::not_equal_to if you require the predicate.
However, if you don't need to use the not_equal_to predicate, you can circumvent the problem entirely by removing all your custom code and adding the following:
#include <utility>
using namespace std::rel_ops;
bool test = a != a;