问题
The following code containing friend declaration fails with indicated error (see http://ideone.com/Kq5dy):
template<class T> void foo() {}
template<typename T>
class A {
void foo();
friend void foo<T>(); // error: variable or field 'foo' declared void
};
int main()
{
foo<int>();
}
If the order of friend declaration and member function declaration reversed, then the code compiles without problems (see http://ideone.com/y3hiK):
template<class T> void foo() {}
template<typename T>
class A {
friend void foo<T>();
void foo();
};
int main()
{
foo<int>();
}
This doesn't happen if the friend declaration doesn't contain template specialization: non-template friends are ok, as well as a template friends. Also using qualified name in template specialization allows code to compile. My question is why does the first example fail? It seems compiler looking up names in class scope at the point of friend declaration and only for template specialization? Where in the Standard this behavior is specified?
回答1:
To make it explicit that it's that function you want to be-friend
prepend the function name with ::
to say that it's in the global namespace.
Snippet that compiles and does what you want:
template<class T> void foo() {}
template<typename T>
class A {
void foo();
friend void ::foo<T>();
};
int main()
{
foo<int>();
}
n1905.pdf
3.4/9 Name Lookup
Name lookup for a name used in the definition of a friend function (11.4) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions. If the friend function is not defined in the class granting friendship, name lookup in the friend function definition shall proceed as described for lookup in namespace member function definitions
Your snippet fails to compile because of the same reason as the code below fails to compile.
template<class T> void foo () {}
template<typename T>
struct A {
void foo ();
void func () {
foo<T> (); // when performing the name lookup A::foo is
// found before ::foo<T>
}
};
...
14.5.3 Friends [temp.friend] 1
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 (non-template) function or class. For a friend function declaration that is not a template declaration:
— if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise
— if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace, the friend declaration refers to that function, otherwise,
— if the name of the friend is a qualified-id and a matching specialization of a function template is found in the specified class or namespace, the friend declaration refers to that function template specialization, otherwise,
— the name shall be an unqualified-id that declares (or redeclares) an ordinary (non-template) function.
来源:https://stackoverflow.com/questions/8514880/friend-declaration-of-template-specialization-fails