C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

unqualified swap calls

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Maxim Yegorushkin
Guest





PostPosted: Thu Sep 08, 2005 11:27 am    Post subject: unqualified swap calls Reply with quote



When I implement swap() as a freestanding non-template function for my
own classes I don't like spelling out qualified calls, I want just use
swap(a, b) and make it find the right swap() via ADL or use std::swap()
if none is found.

Consider this:

#include <algorithm>

namespace N {

class A
{
A(A&);
int operator=(A&);
public:
A();
};
void swap(A&, A&);

class B
{
B(B&);
int operator=(B&);
public:
B();

A a;
int i;
};
void swap(B&, B&);

}

I want to implement void N::swap(B&, B&) using unqualified swap calls.

The first take:

void N::swap(B& m, B& n)
{
using std::swap; // oops, hides all N::swap()'s
swap(m.a, n.a); // calls std::swap() instead of N::swap, ADL does
not kick in [*]
swap(m.i, n.i);
}

The second take:

void N::swap(B& m, B& n)
{
using namespace std; // bring std::swap into the scope
swap(m.a, n.a); // calls N::swap as expected
swap(m.i, n.i); // error: no matching function for call to
swap(int&, int)
}

What I eventually came up with was this:

namespace swapper {

template<class T, class U>
void swap(T& t, U& u)
{
using std::swap;
swap(t, u);
}

} // swapper

This is a function template that uses unqualified argument-dependent
swap() call, which involves ADL and use std::swap() if no
argument-dependent swap is found.

My final take is:

void N::swap(B& m, B& n)
{
using swapper::swap; // hides all N::swap()'s, but it's no problem
anymore
swap(m.a, n.a); // ends up calling N::swap as expected
swap(m.i, n.i); // ends up calling std::swap<int>(int&, int) as
expected
}

I wonder, is there a better solution?

[*] comeau online actually compiles the code, but it's an error
according to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21615


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
tpochep@mail.ru
Guest





PostPosted: Thu Sep 08, 2005 2:06 pm    Post subject: Re: unqualified swap calls Reply with quote



Hi, Maxim.

Quote:
void N::swap(B& m, B& n)
{
using std::swap; // oops, hides all N::swap()'s
swap(m.a, n.a); // calls std::swap() instead of N::swap, ADL does
not kick in [*]
swap(m.i, n.i);
}


This is an error of your compiler (I know, it's a g++ Smile ). And I
think, that Wolfgang's wrong, using declaration can not stop ADL
lookup. In this
example g++ can find both functions (and that's right) and it's an
ambiguity:

namespace N
{
struct A;
}

namespace Odd
{
void fun(N::A&)
{
}
}

namespace N
{
struct A{};

void fun(A&)
{
}
}

int main()
{
using Odd::fun;
N::A a;
fun(a);
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Greg Herlihy
Guest





PostPosted: Fri Sep 09, 2005 3:25 pm    Post subject: Re: unqualified swap calls Reply with quote



Maxim Yegorushkin wrote:
Quote:
When I implement swap() as a freestanding non-template function for my
own classes I don't like spelling out qualified calls, I want just use
swap(a, b) and make it find the right swap() via ADL or use std::swap()
if none is found.

Consider this:

#include <algorithm

namespace N {

class A
{
A(A&);
int operator=(A&);
public:
A();
};
void swap(A&, A&);

class B
{
B(B&);
int operator=(B&);
public:
B();

A a;
int i;
};
void swap(B&, B&);

}

I want to implement void N::swap(B&, B&) using unqualified swap calls.

The first take:

....
The second take:

....
What I eventually came up with was this:

namespace swapper {

template void swap(T& t, U& u)
{
using std::swap;
swap(t, u);
}

} // swapper

This is a function template that uses unqualified argument-dependent
swap() call, which involves ADL and use std::swap() if no
argument-dependent swap is found.

My final take is:

void N::swap(B& m, B& n)
{
using swapper::swap; // hides all N::swap()'s, but it's no problem
anymore
swap(m.a, n.a); // ends up calling N::swap as expected
swap(m.i, n.i); // ends up calling std::swap expected
}

I wonder, is there a better solution?


I would not overlook the obvious solution:

inline void swap( N::B& m, N::B& n )
{
N::swap(m, n); // or implement here
}

Sure, this declaration places the swap function is in the global
namespace. But how global is this routine? It cannot be included
without namespace N. And since both of its parameters are fully
namespace-qualified. there is no chance that this function would
conflict with any other global implementation of swap - unless the N
namespace itself had a conflict.

After all, the namespace N is itself declared in the global namespace.
So isn't this routine:

swap( N::B&, N::b& );

really just as well-specified as this one:

N::swap( B&, B& );

If the answer is yes, then I would see no reason not to declare a
global swap routine for N::B objects.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Branimir Maksimovic
Guest





PostPosted: Fri Sep 09, 2005 3:25 pm    Post subject: Re: unqualified swap calls Reply with quote

Maxim Yegorushkin wrote:
Quote:
When I implement swap() as a freestanding non-template function for my
own classes I don't like spelling out qualified calls, I want just use
swap(a, b) and make it find the right swap() via ADL or use std::swap()
if none is found.

Consider this:

#include
namespace N {

......
void swap(A&, A&);

......
void swap(B&, B&);

}

I want to implement void N::swap(B&, B&) using unqualified swap calls.

The first take:

void N::swap(B& m, B& n)
{
using std::swap; // oops, hides all N::swap()'s
swap(m.a, n.a); // calls std::swap() instead of N::swap, ADL does
not kick in [*]
swap(m.i, n.i);
}


Well, first intuitive try for me was:

namespace N{
//....
using std::swap;
//.....
}

void N::swap(B& m, B& n)
{
swap(m.a, n.a);
swap(m.i, n.i);

}

and it worked, at least with g++ 3.4.2 , though, how's that different
then your first try I have no clue :)

Greetings, Bane.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Sep 09, 2005 3:27 pm    Post subject: Re: unqualified swap calls Reply with quote


[email]tpochep (AT) mail (DOT) ru[/email] wrote:
Quote:
Hi, Maxim.

void N::swap(B& m, B& n)
{
using std::swap; // oops, hides all N::swap()'s
swap(m.a, n.a); // calls std::swap() instead of N::swap, ADL does
not kick in [*]
swap(m.i, n.i);
}


This is an error of your compiler (I know, it's a g++ Smile ). And I
think, that Wolfgang's wrong, using declaration can not stop ADL
lookup.

IMO, g++ and intel are right. I found a similar discussion:
http://groups.google.com/group/comp.std.c++/msg/df34b44ffa0ab483


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Gene Bushuyev
Guest





PostPosted: Sat Sep 10, 2005 12:42 am    Post subject: Re: unqualified swap calls Reply with quote

"Maxim Yegorushkin" <maxim.yegorushkin (AT) gmail (DOT) com> wrote

Quote:

[email]tpochep (AT) mail (DOT) ru[/email] wrote:
Hi, Maxim.

void N::swap(B& m, B& n)
{
using std::swap; // oops, hides all N::swap()'s
swap(m.a, n.a); // calls std::swap() instead of N::swap, ADL does
not kick in [*]
swap(m.i, n.i);
}


This is an error of your compiler (I know, it's a g++ Smile ). And I
think, that Wolfgang's wrong, using declaration can not stop ADL
lookup.

IMO, g++ and intel are right. I found a similar discussion:
http://groups.google.com/group/comp.std.c++/msg/df34b44ffa0ab483

I think that discussion just confirmed that there should be no problem with
ADL here. And mind you, the EDG-based compilers happily compile the code as
soon as you fix the access rights in class B (e.g. granting friendship to
swap function).
Reading Wolfgang's answer I was only wondering where he got that idea, I
can't find anything like that in the standard. Using directive didn't hide
anything, it just added the names to the enclosing namespace thus
contributing to the overload set that compiler has to resolve, nothing more,
nothing less.

- gene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Maxim Yegorushkin
Guest





PostPosted: Mon Sep 12, 2005 9:33 am    Post subject: Re: unqualified swap calls Reply with quote


Gene Bushuyev wrote:

[]

Quote:
I think that discussion just confirmed that there should be no problem with
ADL here. And mind you, the EDG-based compilers happily compile the code as
soon as you fix the access rights in class B (e.g. granting friendship to
swap function).
Reading Wolfgang's answer I was only wondering where he got that idea, I
can't find anything like that in the standard. Using directive didn't hide
anything, it just added the names to the enclosing namespace thus
contributing to the overload set that compiler has to resolve, nothing more,
nothing less.

Could you kindly point to the relevant sections of the standard? I
failed to find them on my own. The current behavior of g++ looks rather
counterintuitive to me.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Gene Bushuyev
Guest





PostPosted: Tue Sep 13, 2005 12:26 am    Post subject: Re: unqualified swap calls Reply with quote

"Maxim Yegorushkin" <maxim.yegorushkin (AT) gmail (DOT) com> wrote

Quote:

Gene Bushuyev wrote:

[]

I think that discussion just confirmed that there should be no problem
with
ADL here. And mind you, the EDG-based compilers happily compile the code
as
soon as you fix the access rights in class B (e.g. granting friendship to
swap function).
Reading Wolfgang's answer I was only wondering where he got that idea, I
can't find anything like that in the standard. Using directive didn't
hide
anything, it just added the names to the enclosing namespace thus
contributing to the overload set that compiler has to resolve, nothing
more,
nothing less.

Could you kindly point to the relevant sections of the standard? I
failed to find them on my own. The current behavior of g++ looks rather
counterintuitive to me.

The relevant sections of the standard are 3.4.1/2

The declarations from the namespace nominated by a using-directive become
visible in a namespace enclosing the using-directive; see 7.3.4. For the
purpose of the unqualified name lookup rules described in 3.4.1, the
declarations from the namespace nominated by the using-directive are
considered members of that enclosing namespace.

and 7.3.4/1, which basically reiterates the same:

A using-directive specifies that the names in the nominated namespace can be
used in the scope in which the using-directive appears after the
using-directive. During unqualified name lookup (3.4.1), the names appear as
if they were declared in the nearest enclosing namespace which contains both
the using-directive and the nominated namespace. [Note: in this context,
"contains" means "contains directly or indirectly". ]

- gene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.