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?
One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function.
A friend function is declared by the class that is granting access. The friend declaration can be placed anywhere in the class declaration. It isn't affected by the access control keywords.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Template declarations (class, function, and variables (since C++14)) can appear inside a member specification of any class, struct, or union that aren't local classes. Partial specializations of member template may appear both at class scope and at enclosing namespace scope.
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>();
}
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.
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