Topic: Non-conforming g++ and msvc for inline friend func? Help appreciated.


Author: "Alf P. Steinbach" <alfps@start.no>
Date: Tue, 4 May 2010 13:15:47 CST
Raw View
(Previously posted to [comp.lang.c++], but it's more of a C++ standard
question. In [comp.lang.c++] Ian Collins reported that also Sun CC fails.)

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

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Sean Hunt <rideau3@gmail.com>
Date: Wed, 5 May 2010 04:30:47 CST
Raw View
On May 4, 1:15 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> Which compiler is right, if any?

Comeau is. The swap functions declared as friends should be completely
invisible to all name lookup until defined outside a class.

> Is there a commonly used solution for this?

GCC seems to compile fine if you use a using-declaration ('using
std::swap') instead of a using-directive ('using namespace std;')

> Or perhaps, just a solution?

Report bugs, get compilers fixed.

> Cheers,
>
> - Alf

Sean


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Alf P. Steinbach" <alfps@start.no>
Date: Wed, 5 May 2010 12:03:50 CST
Raw View
* Sean Hunt:

> * Alf P. Steinbach:
>
>> Which compiler is right, if any?
>>
>
> Comeau is. The swap functions declared as friends should be completely
> invisible to all name lookup until defined outside a class.
>

Given the code presented,


<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


do you mean that if the out-commenting is removed (and also the extra "s"
typo), the Foo::swap function should not be found and it shouldn't compile?

Comeau compiles the Foo::swap call OK.

So if you mean that the Foo:swap call shouldn't compile, do you have
reference to the standard?


Is there a commonly used solution for this?
>>
>
> GCC seems to compile fine if you use a using-declaration ('using
> std::swap') instead of a using-directive ('using namespace std;')
>
> Or perhaps, just a solution?
>>
>
> Report bugs, get compilers fixed.
>

At least four common compilers fail to compile the above: g++ 4.1.1, MSVC
7.1 and 9.0 (different errors), and Sun CC (I don't know the version Ian
used).

Can they all be wrong?

And if they are, what subtlety of the standard is it that they're up
against, and can that subtlety of the standard be fixed?


Cheers,

- Alf

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Wed, 5 May 2010 19:02:03 CST
Raw View
Alf P. Steinbach wrote:

> * Sean Hunt:
>
>> * Alf P. Steinbach:
>>
>>> Which compiler is right, if any?
>>>
>>
>> Comeau is. The swap functions declared as friends should be completely
>> invisible to all name lookup until defined outside a class.
>>
>
> Given the code presented,
>
>
> <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
>
>
> do you mean that if the out-commenting is removed (and also the extra "s"
> typo), the Foo::swap function should not be found and it shouldn't
> compile?
>
> Comeau compiles the Foo::swap call OK.
>
> So if you mean that the Foo:swap call shouldn't compile, do you have
> reference to the standard?

It will compile. ADL will find it.


>>>
>>
>> GCC seems to compile fine if you use a using-declaration ('using
>> std::swap') instead of a using-directive ('using namespace std;')
>>
>> Or perhaps, just a solution?
>>>
>>
>> Report bugs, get compilers fixed.
>>
>
> At least four common compilers fail to compile the above: g++ 4.1.1, MSVC
> 7.1 and 9.0 (different errors), and Sun CC (I don't know the version Ian
> used).
>
> Can they all be wrong?
>
> And if they are, what subtlety of the standard is it that they're up
> against, and can that subtlety of the standard be fixed?
>

The Standard says that the function cannot be found by "simple name lookup"
but only by ADL if you don't provide an explicit declaration in the
namespace: "If a friend declaration in a non-local class first declares a
class or function83) the friend class or function is a member of the
innermost enclosing namespace. The name of the friend is not found by simple
name lookup until a matching declaration is provided in that namespace scope
(either before or after the class declaration granting friendship). If a
friend function is called, its name may be found by the name lookup that
considers functions from namespaces and classes associated with the types of
the function arguments (3.4.2)."
I have no idea why the failing compilers fail. Maybe they think that if they
are in the friend function, they are allowed to find it with namelookup. The
Standard says

"A friend function defined in a class is in the (lexical) scope of the class
in which it is defined.". So maybe they say to itself "ah, the friend
function name is in scope of the class, so we can find it!", but that
Standard paragraph surely intends to say something else (and, in my opinion,
should be no more than a note - the normative text at 3.4.1/9 is already
detailing it).



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: ThosRTanner <ttanner2@bloomberg.net>
Date: Thu, 6 May 2010 20:21:01 CST
Raw View
On May 4, 8:15 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>        friend void swap( Foo&, Foo& ) {}

I thought somewhere that the standard says a friend declaration
doesn't count as a forward declaration / prototype. I know we've got a
lot of stuff that does

class Foo;
void swap(Foo &, Foo &);
...
friend void swap(Foo &, Foo &);

The only thing to be said in its favour is it compiles on all the
compilers we use.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Sean Hunt <rideau3@gmail.com>
Date: Sat, 8 May 2010 07:28:19 CST
Raw View
On May 5, 12:03 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> Given the code presented,
>
> <snip>
>
> do you mean that if the out-commenting is removed (and also the extra "s"
> typo), the Foo::swap function should not be found and it shouldn't compile?

No. It should succeed with or without the commented out line.

> At least four common compilers fail to compile the above: g++ 4.1.1, MSVC
> 7.1 and 9.0 (different errors), and Sun CC (I don't know the version Ian
> used).
>
> Can they all be wrong?

Yes; they can. There are likely obscure corner cases in the standard
that no compilers get correct, though.

> And if they are, what subtlety of the standard is it that they're up
> against, and can that subtlety of the standard be fixed?

A friend declaration of a function (including a definition) is not
visible to name lookup other than ADL. What should happen is that in
both cases, swap is looked up with unqualified lookup and with ADL.
ADL will, in the first line, discover the swap in foo. In both cases,
unqualified lookup will discover the template function swap in the std
namespace. Overload resolution is applied, and the best match is
selected - adl_is_bad::swap for Foo, and std::swap<int> for int. As a
result, the code is well-formed.

Sean


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]