Is this code invalid:
template <class T> struct A;
class C {
template <class T> friend void A<T>::foo();
};
In GCC 6.1.0 it says:
error: member 'void A<T>::foo()' declared as friend before type 'A<T>' defined
template <class T> friend void A<T>::foo();
Clang 3.8.0:
warning: dependent nested name specifier 'A<T>::' for friend class declaration
is not supported; turning off access control for 'C' [-Wunsupported-friend]
And Visual Studio 2015 crashes:
fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\c\template.cpp', line 8952)
template <class T> friend void A<T>::foo();
More specifically, is A required to be defined before the friend declaration?
template <class T> struct A;
class C {
static void foo();
template <class T> friend void A<T>::f();
};
template <class T> struct A {
void f() { }
};
If so, why?
If the friend function is a member of another class, you need to use the scope resolution operator ( :: ). For example: class A { public: int f() { } }; class B { friend int A::f(); }; Friends of a base class are not inherited by any classes derived from that base class.
The function is not in the 'scope' of the class to which it has been declared a friend. Friend functions can be a member of a class or a function that is declared outside the scope of class. It cannot be invoked using the object as it is not in the scope of that class.
In object-oriented programming, a friend function, that is a "friend" of a given class, is a function that is given the same access as methods to private and protected data. A friend function is declared by the class that is granting access, so friend functions are part of the class interface, like methods.
A friend function is a function that isn't a member of a class but has access to the class's private and protected members. Friend functions aren't considered class members; they're normal external functions that are given special access privileges.
You refer to A's member function foo. This function is not known to exist yet, because you only forward declare A.
In other words, you'll have to declare A<T>::foo before C, as the GCC message tries to tell you (the other two are rather cryptic). This means you have to declare the complete interface of A before C, instead of only forward declaring it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With