This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Possible bug for templates friend functions in subclass
- From: "Alan M. Carroll" <amc at network-geographics dot com>
- To: gcc-help at gcc dot gnu dot org
- Date: Thu, 19 Feb 2009 15:04:38 -0600
- Subject: Possible bug for templates friend functions in subclass
I am using GCC 4.2.3 20081105 (Red Hat 4.3.2-7) and having compilation problems with template friends. Here is the code
// -- code start
template <typename T> class foo;
template <typename T> inline void bar(foo<T> const* f);
template <typename T>
class foo {
protected:
friend void bar<>(foo<T> const*);
mutable long x;
};
template <typename T> inline void bar(foo<T> const* f) { --(f->x);}
class child : public foo<child> {
friend void bar<>(foo<child> const*);
};
void func() {
child c;
bar(&c);
}
// -- code end
This is based on the example in the FAQ on declaring friends with templated functions and classes. The compile error is
gcc-friend.cpp: In function ?void bar(const foo<T>*) [with T = child]?:
gcc-friend.cpp:20: instantiated from here
gcc-friend.cpp:9: error: ?long int foo<child>::x? is protected
gcc-friend.cpp:12: error: within this context
This shouldn't happen because both child and foo<child> have function bar(foo<child> const*) as a friend. However, if the friend declaration in class child is removed, then the code compiles without error. In the real code I need to have that declaration because this is a CRTP pattern where function bar needs to access a potentially non-public member of the T passed as a template parameter to class foo.
It seems to me that the problem is gcc is not matching up the two declarations of bar in the friend as the same instantiation of the template even though it matches both of them against the forward declaration of bar (as can be verified by changing the signature). Making the forward declaration the definition has no effect.
My question is -- is this a bug, and if not, how do I convince gcc that the two friend declarations of bar are the same instantiation? The standard solution is a forward declare in the correct scope but I already have that.