Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > What swap is called when using std::swap?

Reply
Thread Tools

What swap is called when using std::swap?

 
 
Niels Dekker (no reply address)
Guest
Posts: n/a
 
      07-19-2006
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 T> void 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
 
Reply With Quote
 
 
 
 
werasm
Guest
Posts: n/a
 
      07-19-2006

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 T> void 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

 
Reply With Quote
 
 
 
 
Howard Hinnant
Guest
Posts: n/a
 
      07-19-2006
In article <(E-Mail Removed)>,
"Niels Dekker (no reply address)" <(E-Mail Removed)> wrote:

> 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 T> void 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
 
Reply With Quote
 
werasm
Guest
Posts: n/a
 
      07-19-2006

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

 
Reply With Quote
 
Niels Dekker (no reply address)
Guest
Posts: n/a
 
      07-20-2006
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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
newbie -- smart pointer destructor called without destructor everbeing called Jimmy Hartzell C++ 2 05-20-2008 02:20 AM
newbie -- smart pointer destructor called without destructor everbeing called Jimmy Hartzell C++ 0 05-19-2008 07:05 PM
Why is a button Click event also called when a textbox TextChanged event is called??? S_K ASP .Net 6 11-08-2007 07:44 PM
What is called carry chain structure in FPGA is called in IC? Weng Tianxiang VHDL 6 09-12-2007 07:19 AM
three times copy ctor called, one ctor called, why? Apricot C++ 4 04-16-2004 07:55 AM



Advertisments