By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,088 Members | 1,296 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,088 IT Pros & Developers. It's quick & easy.

What swap is called when using std::swap?

P: n/a
When calling swap as follows (as recommanded in Effective C++, 3rd
Edition, by Scott Meyers), what swap is chosen to be called?
using std::swap;
swap(a, b);

Suppose there is a global ::swap function provided, whose parameter type
matches closer to the type of a and b than any of the std::swap
overloads does. Will this ::swap be called, or is std::swap still
preferred? I ask this because the compilers I tried disagree! So will
any of the ::swap functions I defined down below be called in the
following main()?

#include <algorithm>
struct Foo {};

void swap(int &, int &) {}
void swap(Foo &, Foo &) {}
template<typename Tvoid swap(T*&, T*&) {}

int main()
{
using std::swap;

int i1, i2;
swap(i1, i2);

int *ptr1, *ptr2;
swap(ptr1, ptr2);

Foo foo1, foo2;
swap(foo1, foo2);

Foo *foo_ptr1, *foo_ptr2;
swap(foo_ptr1, foo_ptr2);
}

To my surprise, MSVC++ 8.0 prefers to call std::swap for int and int*.
It only calls ::swap for Foo and Foo*. But GNU g++ 3.4.4 surprises me
even more, as it never calls any of my ::swap overloads at all, and
always prefers calling std::swap instead! So what's the Standard
compliant way?
Kind regards

Niels Dekker
xs4all.nl/~nd/dekkerware
Jul 19 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a

Niels Dekker (no reply address) wrote:
When calling swap as follows (as recommanded in Effective C++, 3rd
Edition, by Scott Meyers), what swap is chosen to be called?
using std::swap;
swap(a, b);

Suppose there is a global ::swap function provided, whose parameter type
matches closer to the type of a and b than any of the std::swap
overloads does. Will this ::swap be called, or is std::swap still
preferred?
"using std::swap" would mean std::swap would be taken into
consideration when establishing the initial overload set. Usually, when
all aspects of overload resolution are equal, non-templates would be
preferred.
#include <algorithm>
struct Foo {};

void swap(int &, int &) {}
void swap(Foo &, Foo &) {}
template<typename Tvoid swap(T*&, T*&) {}

int main()
{
using std::swap;

int i1, i2;
swap(i1, i2);

I would call you swap(int&,int&) a perfect match here, and would put my
money on it being called everytime.

>
int *ptr1, *ptr2;
swap(ptr1, ptr2);
Your (template) version of swap is more specialized than the std::swap
- therefore it should be called here (I'm using SGI std::swap as
reference).

SGI...
template <class Assignable>
void swap(Assignable& a, Assignable& b);
....
It may be possible that other libs have more specialized swaps for
pointers. If this is the case (IMO), you should get ambiguities.
>
Foo foo1, foo2;
swap(foo1, foo2);
void swap(Foo &, Foo &), for the same reason - non-templates preferred.
>
Foo *foo_ptr1, *foo_ptr2;
swap(foo_ptr1, foo_ptr2);
Once again, your template version is more specialized.

}

To my surprise, MSVC++ 8.0 prefers to call std::swap for int and int*.
This is surprising IMhO, and would like someone to educate me too in
the event of me being wrong :-). I don't consider the compilers std
compliant, but I may be wrong.

Kind regards,

Werner

Jul 19 '06 #2

P: n/a
In article <44***************@this.is.invalid>,
"Niels Dekker (no reply address)" <un*****@this.is.invalidwrote:
Will this ::swap be called, or is std::swap still
preferred? I ask this because the compilers I tried disagree! So will
any of the ::swap functions I defined down below be called in the
following main()?

#include <algorithm>
struct Foo {};

void swap(int &, int &) {}
void swap(Foo &, Foo &) {}
template<typename Tvoid swap(T*&, T*&) {}

int main()
{
using std::swap;

int i1, i2;
swap(i1, i2);

int *ptr1, *ptr2;
swap(ptr1, ptr2);

Foo foo1, foo2;
swap(foo1, foo2);

Foo *foo_ptr1, *foo_ptr2;
swap(foo_ptr1, foo_ptr2);
}

To my surprise, MSVC++ 8.0 prefers to call std::swap for int and int*.
It only calls ::swap for Foo and Foo*. But GNU g++ 3.4.4 surprises me
even more, as it never calls any of my ::swap overloads at all, and
always prefers calling std::swap instead! So what's the Standard
compliant way?
swap(i1, i2);

This calls std::swap. The function-local using declaration hides the
global swaps from ordinary lookup, but not ADL. The global swap isn't
found via ADL because there is no namespace associated with int.

swap(ptr1, ptr2);

This calls std::swap, for the same reasons as the previous call.

swap(foo1, foo2);

This calls ::swap(Foo&,Foo&). Ordinary lookup does not find this, but
ADL kicks in and searches the namespace associated with Foo (global).

swap(foo_ptr1, foo_ptr2);

This calls ::swap(T*&, T*&). Ordinary lookup does not find this, but
ADL kicks in and searches the namespace associated with Foo (global).

An interesting experiment is to move the using declaration to namespace
scope (above main), and reexamine.

-Howard
Jul 19 '06 #3

P: n/a

Howard Hinnant wrote:
This calls std::swap. The function-local using declaration hides the
global swaps from ordinary lookup, but not ADL. The global swap isn't
found via ADL because there is no namespace associated with int.
Interesting. I was under the impression that because main is defined in
the global scope, using declarations in it become associated with the
global scope. This is obviously wrong - it becomes associated with the
function scope, which takes precedence over the global scope. Therefore
the initial overload set considered is that within function scope
(which is what can be found via ADL and what is part of function scope
by local using). I thought I would learn by taking the shot :-)

An interesting experiment is to move the using declaration to namespace
scope (above main), and reexamine.
Quick guess is that it will work iaw. with my original thought, as the
global swaps and std::swap would form part of the same overload set,
and the OP's swaps are more specialized?

Kind regards,

W

Jul 19 '06 #4

P: n/a
Thanks very much to you both, Werner and Howard!
int main()
{
using std::swap;

int i1, i2;
swap(i1, i2);
Howard Hinnant wrote:
This calls std::swap. The function-local using declaration hides the
global swaps from ordinary lookup, but not ADL. The global swap isn't
found via ADL because there is no namespace associated with int.

It's clear to me now :-)
Kind regards,

Niels
Jul 20 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.