This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: Internal error, RHv6.0 i386 gcc v2.95.2
> Are you sure it's fixed? Unless I'm mistaken, line 386 is merely
> declaring a friend template class, not specializing the class.
I'm not sure whether it is fixed; I'm having difficulties interpreting
the standard here. My current interpretation is that this is
ill-formed for syntactical reasons; the error message of g++ might be
misleading, though.
Your simplified example is a big help, let's study this instead. I
take this really slow, with bullet items so you can skip elaborations
you agree to.
> namespace one {
> template <class T>
> class A {};
> };
>
> namespace two {
> class B {
> template <class T>
> friend class one::A<T>;
> };
> };
>
> int main(int argc, char** argv)
> {
> two::B b;
> }
Looking at
template <class T> friend class one::A<T>;
I ask: What kind of declaration is this? 14.5.3, [temp.friend]/1 says
# A friend of a class or class template can be a function template or
# class template, a specialization of a function template or class
# template, or an ordinary (nontemplate) function or class.
A. So your claim is that the friend is the class template, not a
specialization.
Let's assume for a moment that this does not refer to a class
template. 14.5.3/1 then goes on
# For a friend function declaration that is not a template
# declaration:
# if the name of the friend is a qualified or unqualified
# templateid, the friend declaration refers to a specialization of
# a function template, otherwise
I guess the 'name of the friend' here is 'one::A<T>', so *it is* a
qualified template-id. So it should be a specialization of a
function template? How can I declare class template specializations
as friends, then? Perhaps the 'name of the friend' is 'class
one::A<T>'? Let's go on and assume that this does not apply
# if the name of the friend is a qualifiedid and a matching
# nontemplate function is found in the specified class or
# namespace, the friend declaration refers to that function,
# otherwise,
No, we did not find a matching function
# if the name of the friend is a qualifiedid and a matching
# specialization of a template function is found in the specified
# class or namespace, the friend declaration refers to that
# function specialization, otherwise,
No, we did not find a matching specialization, either
# the name shall be an unqualifiedid that declares (or redeclares)
# an ordinary (nontemplate) function.
No, the name is not an unqualified-id. So the code is in error, it
would appear. Interestingly, it does not allow for specializations
being friends, which are then given in the example:
# friend class task<int>;
B. Since we want the template to be the friend, apparently we must put
a template declaration into the friend declaration. However, this
is not the syntax of a template declaration.
14.5, [temp.decls]/1 specifies
# A templateid, that is, the templatename followed by a
# templateargumentlist shall not be specified in the declaration
# of a primary template declaration.
This does not explicitly mention a friend declaration, but an
(non-normative) note explains what the exceptions are
# [Note: however, this syntax is allowed in class template partial
# specializations (14.5.4). ]
Since this is not what we want to do, it seems that we must not put
the template-id in the friend declaration.
C. After correcting the example as
namespace one {
template <class T>
class A {};
};
namespace two {
class B {
template <class T>
friend class one::A;
};
};
int main(int argc, char** argv)
{
two::B b;
}
g++ accepts it just fine.
Without checking, it seems that g++ sees a qualified template
id. Looking at above rules, it knows that this must be a
specialization, and then finds several problems in that assumption.
If you question this line of reasoning, I'd prefer if you discuss it
in one of the public C++ fora first, eg. comp.lang.c++.moderated, or
comp.std.c++. However, if you can tell me right-away where I erred,
I'd be happy to be corrected.
Regards,
Martin