There is actually a number of problems in your code that cause the error message. And one contributor to the problem due to your implementation (i.e. the standard library you are using).
Firstly, you have defined a templated swap()
with the same form (accepting two objects of the same type by reference) as an existing function named swap()
.
Second, the using namespace std
tells the compiler that names in namespace std
are candidates for matching names in your code. So, when the compiler sees your code swap(m,n)
where m
and n
are int
, it sees both your definition and the one in namespace std
(i.e. std::swap()
as viable candidates to match the name swap()
in your code. Both candidates are able to accept two arguments of type (reference to) int
, so the compiler has no reason to prefer one over the other. Hence it rejects your code with an error message about ambiguity.
The third problem is in your implementation (i.e. your compiler and its associated standard library) - <iostream>
has apparently drawn in the definition of std::swap()
. The problem is that <iostream>
is neither required to do that (i.e. you cannot rely on it happening if you build your code with a different compiler) nor required not to (i.e. your code will compile alright with some compilers/libraries but not others).
In reality, std::swap()
is required by the standard to be declared in <algorithm>
, not in <iostream>
.
Your options to get your code working with ALL compilers are therefore simple. A first option is to not define your own swap()
at all, and rely on the standard library.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
using namespace std;
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A second option is to rename your function so it does not clash with std::swap()
.
#include <iostream>
using namespace std;
template <typename T>
void your_swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
your_swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A third option is to remove using namespace std
from your code. This will allow you to safely declare your own swap()
, without clashes with std::swap()
.
#include <iostream>
#include <algorithm>
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
This last example will actually compile nicely - even with <algorithm>
deliberately being used to draw in declarations of std::swap()
- because the compiler has not been told to view names in std
as candidates. It does require adding std::
prefixes to names in namespace std
(std::cout
, std::endl
) that you intend to use. It will also compile nicely if swap(m,n)
is replaced by std::swap(m,n)
.
A fourth option (which I normally would prefer in professional coding) is to rely on the standard library AND not employ using namespace std
.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
std::swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
The short explanation of my preference for this option is that it avoids various other problems of ambiguity as well. The saved typing of not having to prefix std::
on names is not worth the trouble caused when other problems of ambiguity emerge.