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

  • Thread starter Alf P. Steinbach
  • Start date
A

Alf P. Steinbach

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
 
I

Ian Collins

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"?
 
A

Alf P. Steinbach

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&).


I'll leave that bit to a language lawyer!


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
 
A

Alf P. Steinbach

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&).


I'll leave that bit to a language lawyer!

OK, I'll post this to [comp.std.c++].


Cheers, & thanks,

- Alf
 
P

Paul Bibbings

Alf P. Steinbach said:
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
 
P

Paul Bibbings

Alf P. Steinbach said:
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
 
A

Alf P. Steinbach

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
 
P

Paul Bibbings

Alf P. Steinbach said:
On 04.05.2010 16:06, * Paul Bibbings:

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top