![]() |
Non-conforming g++ and msvc for inline friend func? Help appreciated.
Comeau compiles fine, g++ and msvc fail.
<code file="x.cpp"> #include <algorithm> namespace adl_is_bad { struct Foo { friend void swap( Foo&, Foo& ) {} }; struct Bar { Foo myFoo; int myInt; Bar(): myInt( 0 ) {} friend void swap( Bar& a, Bar& b ) { using namespace std; //sswap( a.myFoo, b.myFoo ); swap( a.myInt, b.myInt ); } }; } // namespace adl_is_bad int main() {} </code> <comeau> Your Comeau C/C++ test results are as follows: Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors C++ C++0x_extensions In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link). Compiled with C++0x extensions enabled. </comeau> <g++ 4.4.1> C:\test> gnuc --version g++ (TDM-2 mingw32) 4.4.1 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. C:\test> gnuc x.cpp x.cpp: In function 'void adl_is_bad::swap(adl_is_bad::Bar&, adl_is_bad::Bar&)': x.cpp:21: error: 'swap' was not declared in this scope C:\test> _ </g++ 4.4.1> <msvc 7.1> C:\test> msvc --version Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.6030 for 80x86 Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] C:\test> msvc x.cpp x.cpp x.cpp(21) : error C3767: 'swap' matching function is not accessible could be the friend function at 'x.cpp(7)' : 'swap' [may be found via argument-dependent lookup] or the friend function at 'x.cpp(17)' : 'swap' [may be found via argument-dependent lookup] C:\test> _ </msvc 7.1> <msvc 9.0> C:\test> msvc --version Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] C:\test> msvc x.cpp x.cpp x.cpp(21) : error C2664: 'void adl_is_bad::swap(adl_is_bad::Bar &,adl_is_bad::Bar &)' : cannot convert parameter 1 from 'int' to 'adl_is_bad::Bar &' C:\test> _ </msvc 9.0> Which compiler is right, if any? Is there a commonly used solution for this? Or perhaps, just a solution? Cheers, - Alf |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
On 05/ 4/10 01:25 PM, Alf P. Steinbach wrote:
> Comeau compiles fine, g++ and msvc fail. > > > <code file="x.cpp"> > #include <algorithm> > > namespace adl_is_bad { > > struct Foo > { > friend void swap( Foo&, Foo& ) {} > }; > > struct Bar > { > Foo myFoo; > int myInt; > > Bar(): myInt( 0 ) {} > > friend void swap( Bar& a, Bar& b ) > { > using namespace std; > //sswap( a.myFoo, b.myFoo ); > swap( a.myInt, b.myInt ); > } > }; > > } // namespace adl_is_bad > Sun CC also complains: Could not find a match for adl_is_bad::swap(int, int) needed in adl_is_bad::swap(adl_is_bad::Bar&, adl_is_bad::Bar&). > Which compiler is right, if any? I'll leave that bit to a language lawyer! > Is there a commonly used solution for this? Use "std::swap"? -- Ian Collins |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
On 04.05.2010 03:43, * Ian Collins:
> On 05/ 4/10 01:25 PM, Alf P. Steinbach wrote: >> Comeau compiles fine, g++ and msvc fail. >> >> >> <code file="x.cpp"> >> #include <algorithm> >> >> namespace adl_is_bad { >> >> struct Foo >> { >> friend void swap( Foo&, Foo& ) {} >> }; >> >> struct Bar >> { >> Foo myFoo; >> int myInt; >> >> Bar(): myInt( 0 ) {} >> >> friend void swap( Bar& a, Bar& b ) >> { >> using namespace std; >> //sswap( a.myFoo, b.myFoo ); >> swap( a.myInt, b.myInt ); >> } >> }; >> >> } // namespace adl_is_bad >> > Sun CC also complains: > > Could not find a match for adl_is_bad::swap(int, int) needed in > adl_is_bad::swap(adl_is_bad::Bar&, adl_is_bad::Bar&). > >> Which compiler is right, if any? > > I'll leave that bit to a language lawyer! > >> Is there a commonly used solution for this? > > Use "std::swap"? Yeah, but imagine that the 'int' is a template parameter type. Then one wouldn't want to impose std::swap? Cheers, - Alf |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
On 04.05.2010 03:43, * Ian Collins:
> On 05/ 4/10 01:25 PM, Alf P. Steinbach wrote: >> Comeau compiles fine, g++ and msvc fail. >> >> >> <code file="x.cpp"> >> #include <algorithm> >> >> namespace adl_is_bad { >> >> struct Foo >> { >> friend void swap( Foo&, Foo& ) {} >> }; >> >> struct Bar >> { >> Foo myFoo; >> int myInt; >> >> Bar(): myInt( 0 ) {} >> >> friend void swap( Bar& a, Bar& b ) >> { >> using namespace std; >> //sswap( a.myFoo, b.myFoo ); >> swap( a.myInt, b.myInt ); >> } >> }; >> >> } // namespace adl_is_bad >> > Sun CC also complains: > > Could not find a match for adl_is_bad::swap(int, int) needed in > adl_is_bad::swap(adl_is_bad::Bar&, adl_is_bad::Bar&). > >> Which compiler is right, if any? > > I'll leave that bit to a language lawyer! OK, I'll post this to [comp.std.c++]. Cheers, & thanks, - Alf |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
"Alf P. Steinbach" <alfps@start.no> writes:
> Comeau compiles fine, g++ and msvc fail. > > > <code file="x.cpp"> > #include <algorithm> > > namespace adl_is_bad { > > struct Foo > { > friend void swap( Foo&, Foo& ) {} > }; > > struct Bar > { > Foo myFoo; > int myInt; > > Bar(): myInt( 0 ) {} > > friend void swap( Bar& a, Bar& b ) > { > using namespace std; > //sswap( a.myFoo, b.myFoo ); > swap( a.myInt, b.myInt ); > } > }; > > } // namespace adl_is_bad > > int main() {} > </code> > Just a quick question, while I think this through. I can accept that there is a question here about which compilers are performing correctly, but what has this to do with ADL? Your arguments to swap( a.myInt, b.myInt ) are (obviously) of type int; that is, they are of fundamental type. Given that, ADL applies... how? Regards Paul Bibbings |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
"Alf P. Steinbach" <alfps@start.no> writes:
> Comeau compiles fine, g++ and msvc fail. > > > <code file="x.cpp"> > #include <algorithm> > > namespace adl_is_bad { > > struct Foo > { > friend void swap( Foo&, Foo& ) {} > }; > > struct Bar > { > Foo myFoo; > int myInt; > > Bar(): myInt( 0 ) {} > > friend void swap( Bar& a, Bar& b ) > { > using namespace std; > //sswap( a.myFoo, b.myFoo ); > swap( a.myInt, b.myInt ); > } > }; > > } // namespace adl_is_bad > > int main() {} > </code> > Just as a first thought, although I'm not offering this as `correct' in any sense, as I'm not near my copy of the Standard at the moment and will need to do some digging. Suppose, for the sake of a playing devils-advocate and attempting to support the compilers that fails this code, we look at the following: 1. the inline definition of swap in struct Foo introduces swap(Foo&, Foo&) into namepspace adl_is_bad; that is: void adl_is_bad::swap(Foo&, Foo&) 2. likewise, the inline definition of swap(Bar&, Bar&) in struct Bar introduces into adl_is_bad: void adl_is_bad::swap(Bar&, Bar&) Now - and this is the part that I will need to look up... Isn't it the case in name lookup that, when a name is found *directly*, other names introduced by using directives that might otherwise be found are *not* considered? I'll check this, but if it were the case, then the call to swap(a.myInt, b.myInt) from swap(Bar&, Bar&) would find both these declarations, but not std::swap, since that would not be considered owing to it being introduced via a using directive. These are just some thoughts prior to working out what's really going on, so please ignore if totally incorrect. :-) Regards Paul Bibbings |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
On 04.05.2010 16:06, * Paul Bibbings:
> "Alf P. Steinbach"<alfps@start.no> writes: > >> Comeau compiles fine, g++ and msvc fail. >> >> >> <code file="x.cpp"> >> #include<algorithm> >> >> namespace adl_is_bad { >> >> struct Foo >> { >> friend void swap( Foo&, Foo& ) {} >> }; >> >> struct Bar >> { >> Foo myFoo; >> int myInt; >> >> Bar(): myInt( 0 ) {} >> >> friend void swap( Bar& a, Bar& b ) >> { >> using namespace std; >> //sswap( a.myFoo, b.myFoo ); >> swap( a.myInt, b.myInt ); >> } >> }; >> >> } // namespace adl_is_bad >> >> int main() {} >> </code> >> > > Just a quick question, while I think this through. I can accept that > there is a question here about which compilers are performing correctly, > but what has this to do with ADL? Your arguments to swap( a.myInt, > b.myInt ) are (obviously) of type int; that is, they are of fundamental > type. Given that, ADL applies... how? First, the technique illustrated is in support of ADL. Otherwise there wouldn't be much point to doing it this way (indeed this possibility, not having to know whcih 'swap', is as I perceive it the most often cited argument in favor of ADL). Secondly, with MSVC 7.1 the error message specifically mentions ADL. So I guess that the intricacies ADL is part of the answer, but also perhaps namespace subtleties (putting the code in the global namespace => works!) and friend function injection subtleties & convoluted history of semantics changes. Anyway, I "solved" it by applying a workaround /convention/: * Every class supporting swapping defines a public method 'swapWith'. * Every such class also places a corresponding free 'swap' function in the global namespace. * To support the latter I defined a macro CPPX_IMPLEMENT_SWAP. :-) Note: the original article has now been posted and published in [comp.std.c++]. I think that's a better forum for this question. Cheers, - Alf |
Re: Non-conforming g++ and msvc for inline friend func? Help appreciated.
"Alf P. Steinbach" <alfps@start.no> writes:
> On 04.05.2010 16:06, * Paul Bibbings: <snip /> >> Just a quick question, while I think this through. I can accept that >> there is a question here about which compilers are performing correctly, >> but what has this to do with ADL? Your arguments to swap( a.myInt, >> b.myInt ) are (obviously) of type int; that is, they are of fundamental >> type. Given that, ADL applies... how? > > First, the technique illustrated is in support of ADL. Otherwise there > wouldn't be much point to doing it this way (indeed this possibility, > not having to know whcih 'swap', is as I perceive it the most often > cited argument in favor of ADL). Secondly, with MSVC 7.1 the error > message specifically mentions ADL. I'm not sure what your first statement means, that "the technique illustrated is in support of ADL." There is certainly the potential for the friend functions to be found using ADL, if that is what you mean. Then, as to your second point above, that is really all the VS error messages are reporting... > C:\test> msvc x.cpp > x.cpp > x.cpp(21) : error C3767: 'swap' matching function is not accessible > could be the friend function at 'x.cpp(7)' : 'swap' [may be > found via argument-dependent lookup] > or the friend function at 'x.cpp(17)' : 'swap' [may be > found via argument-dependent lookup] .... that is to say, that whilst the functions: adl_is_bad::swap(Foo&, Foo&) // line 7 and: adl_is_bad::swap(Bar&, Bar&) // line 17 `may be' found via argument-dependent lookup, they are *in fact* not considered simply for the point that I was trying to make; that, in your example, calling swap with *int* arguments, you are not actually invoking adl at all. Or... to soften that statement then, perhaps it's more correct to say that ADL /does/ apply, but that it cannot succeed nevertheless. In the context of ADL, as you know, the concepts of associated namespaces and associated classes are central. But of course, as [basic.koenig.lookup]/2 states: "If T is a fundamental type, its associated sets of namespaces and classes are both empty." Following from this, taking the viewpoint that ADL is being applied but that the set of associated namespaces and classes are both empty, perhaps [basic.koenig.lookup]/3 is being applied in the failing cases nevertheless. That is: "Any using-directives in the associated namespace are ignored." This, however, is not to support those implementations, since this point should not, IMHO, be relevant when the set is empty, as there are then *no* associated namespaces. But it may go some way to getting an insight into just what /might/ be going wrong. It looks possible that the error, if error there is, is that the implementations that reject your code, whilst finding the set of associated namespaces empty, nevertheless are continuing to reject the using directive (according to para 3) which would otherwise find std::swap. <snip /> Regards Paul Bibbings |
| All times are GMT. The time now is 02:13 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.