Re: friends, templates and comeau, gcc
On Nov 30, 11:58 am, werasm <wer...@gmail.com> wrote:
I have this (minimal) piece of code that does not compile
under comeau (online) and gcc 4.2.1.
namespace n{
template <class T> struct X
I don't think the fact that X is a template is relevant here. I
think you'll have the same problem with an ordinary class.
{
friend int foo( X ){ return 0; }
};
}//!n
int main()
{
n::X<int> x;
return n::foo( x );
}
Comeau output:
"ComeauTest.c", line 15: error: namespace "n" has no member "foo"
return n::foo( x );
A better message would be ``namespace "n" has no visible member
"foo"''. Namespace n clearly has a member foo, but it's not
been declared in a scope which would make it visible here.
When removing the namespace qualification, everything compiles fine,
therefore...
[...as before...]
int main()
{
n::X<int> x;
return foo( x );
}
Yep. When you say n::..., you're telling the compiler
explicitly to look at what is visible in n (which doesn't
necessarily contain everything that is in n). When you leave
the qualification off, you're telling the compiler to look at
what is normally visible at the call site, *and* at any
additional scopes introduced by ADL. In this case, ADL
introduces the scope of n::X, and in the scope of n::X, there is
a declaration which makes n::foo visible.
...now compiles without errors.
Changing the example slightly to here below:
namespace n{
template <class T> class X;
template <class T> int foo( X<T> )
{ return 0; }
template <class T>
struct X
{
friend int foo<>( X<T> );
};
}//!n
int m()
{
n::X<int> x;
return n::foo( x );
}
Does not result in the error (irrespective of whether n is
qualified or not). I have not checked gcc with respect to
this.
Can anybody perhaps give an explanation concerning this
behaviour. Is this perhaps a compiler bug?
No bug, although probably not very intuitive. Just because
something exists in a given namespace doesn't mean that it is
visible in a given scope. A declaration must be visible in that
scope for it to be visible. A friend declaration isn't in the
surrounding namespace scope, but rather in the class, so it
only makes the symbol visible in the class scope. In your last
example, you have a declaration in the scope itself, so the
symbol becomes visible anytime lookup considers the scope.
--
James Kanze