Why do I get a template error if I name my function `swap`, but `Swap` is okay?
This is because there already exists a function called swap
. It is actually under the std
namespace, but because you have a using namespace std
line, it exists without the std::
prefix.
As you can see, using the using namespace std
isn't always a good option because of possible name collisions, as in this example. In general one should prefer not to use the using
directive unless there's a real reason for this - namespaces exist for a reason - to prevent name collisions.
Why is this swap function call ambiguous?
#include <iostream>
using namespace std;
iostream
must be including algorithm
and, since you decided to include the entire std
namespace in your file, you have a collision with std::swap
. Remove using namespace std;
EDIT: As @chris points out in the comments, std::swap
was moved to <utility>
in C++11.
Call of overloaded function is ambiguous... But Why? Template problem
As mentioned in the comment you should do some changes to remove the ambiguity between the std::swap and yours. remove using namespace std;
and use std::
before cout
:
#include <iostream>
template<typename T>
void swap(T &a, T &b)
{
T dummy = a;
a = b;
b = dummy;
}
template<typename T>
void swap(T a[], T b[], int size)
{
for(int i = 0; i < size;i++)
{
T dum = a[i];
a[i] = b[i];
b[i] = dum;
}
}
int main()
{
int a = 20;
int b = 10;
swap(a, b);
std::cout << "a: " << a << "\t" << "b: " << b << std::endl;
int eights[] = {8, 8, 8, 8, 8, 8, 8};
int threes[] = {3, 3, 3, 3, 3, 3, 3};
for(int i = 0; i <7;i++)
{
std::cout << eights[i] << "\t";
}
for(int i = 0; i <7;i++)
{
std::cout << threes[i] << "\t";
}
swap(eights, threes, 7);
for(int i = 0; i <7;i++)
{
std::cout << eights[i] << "\t";
}
for(int i = 0; i <7;i++)
{
std::cout << threes[i] << "\t";
}
}
Why name lookup can't find std::swap when a base class has a swap function in C++?
For unqualified name lookup:
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
So the name swap
is examined in class A
firstly, it's not found, then examined in class Parent
, it's found, then name lookup stops. std::swap
introduced into global scope won't be found at all.
And
Why the ADL here can't find the
std::swap
and use it ?
You're passing long
s to swap
, while ADL works with class types, but not fundamental types.
- For arguments of fundamental type, the associated set of namespaces and classes is empty
BTW: In this special case even you change to pass some class types defined in std
namespace to swap
ADL won't be considered either.
First, the argument-dependent lookup is not considered if the lookup set produced by usual unqualified lookup contains any of the following:
- a declaration of a class member
Parent::swap
is a class member which is found by usual unqualified name lookup, ADL still won't be considered.
How do I make std::sort not have name collision between std::swap and my namespace's templated swap?
A workaround is to create a better overload:
// No modifiable code
namespace my
{
template<class T> void swap(T a, T b) { /*.. */ }
struct Obj { /*..*/ };
}
// Your code:
namespace my
{
void swap(Obj& lhs, Obj& rhs)
{
// my::swap<Obj&>(lhs, rhs);
std::swap(lhs, rhs);
}
}
// In namespace you want.
void doSortStuff()
{
std::vector<my::Obj> arr;
std::sort(arr.begin(), arr.end());
}
Then, between the 3 valid overloads, all are exact match, but the non-template is preferred.
Ambiguous call to overloaded function (learning about templates)
You are redefining the function swap with the same signature, so you're having an ambiguous definition of it, and, consequently, an ambiguous call.
If you want to maintain the function with the same signature, you should either choose to use not the "using namespace std;", which will not shadow your swap() definition, or simply define tthe function in another namespace.
Example:
namespace your_namespace {
template <typename X>
void swap(X &a, X &b) {
X temp = a;
a = b;
b = temp;
}
}
int foo(10), bar(20);
std::cout << "foo: " << foo << "; bar: " << bar << std::endl;
your_namespace::swap(foo, bar);
std::cout << "foo: " << foo << "; bar: " << bar << std::endl;
Output:
foo: 10; bar: 20
foo: 20; bar: 10
Regards!
Is there any coincidences I've done while templatizing this function in C++, using void swap()?
You should just use std::swap
rather than your own.
But, for an explanation of your error:
using namesapce std;
Assuming that actually says namespace
in your code, that is the problem. There is a swap
in namespace std
.
If you remove the using
directive and qualify your std uses with std::
then you can call your swap unqualified live link
#include <iostream>
#include <string>
template <typename T>
void swap(T &a, T &b) {
T temp = a; //Temporary copy to reuse
// a = (b = temp); // incorrect
a = b;
b = temp;
}
int main() {
int x, y;
std::cin >> x >> y;
std::cout << "X: " << x << "\t Y: " << y << '\n';
swap(x, y);
}
As to why it happens to work with std::string
: there is a overload of std::swap
for strings that is a better match than your templated swap, so the compiler unambiguously picks that one
https://en.cppreference.com/w/cpp/string/basic_string/swap2
Related Topics
Programmatically Check Whether My MAChine Has Internet Access or Not
Equality-Compare Std::Weak_Ptr
How to Build a Program Using C++ Driver of Mongodb
Why Can't I Assign an Array Variable Directly to Another Array Variable with the '=' Operator
How to Set Given Channel of a Cv::Mat to a Given Value Efficiently Without Changing Other Channels
Macros in the Middle of a Class or Function Declaration
Why Does (1 << 31) >> 31 Result in -1
Undefined Behavior in C/C++: I++ + ++I VS ++I + I++
What Does "-Wall" in "G++ -Wall Test.Cpp -O Test" Do
How to Overload the Conditional Operator
Combining Two Lists by Key Using Thrust
Auto Keyword Behavior with References
Using Sendmessage to Send Wm_Close to Another Process
How to Swap Array-Elements to Transfer the Array from a Column-Like into a Row-Like Representation
Converting Integer into Array of Digits
How to Check If Std::Map Contains a Key Without Doing Insert
How to Expand Environment Variables in .Ini Files Using Boost