Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An explicit specialization cannot be a friend declaration

The code

template <typename T>
void foo(const T& t)
{}

template <typename T>
class A
{
    template <>
    friend void foo<T>(const T& t)
    {}
};

gives compile error

"defining explicit specialization ‘foo<T>’ in friend declaration friend void foo<T>(const T& t)"

when compiling with gcc and

"error C3637: 'A<int>::foo' : a friend function definition cannot be a specialization of a unction template"

when compiling in VS2013

I understand that standard says so, but why? I want to understand the reason(under the hood) There are many articles where written "An explicit specialization cannot be a friend declaration.", but I can't understand why. Any ideas?

like image 472
Vahagn Babajanyan Avatar asked Jan 04 '15 15:01

Vahagn Babajanyan


1 Answers

Declaring an explicit specialization inside a class template for the first (and possibly only) time would mean that the explicit specialization is only "existing" once the template has been instantiated - regardless from whether the declaration is dependent on a template parameter or not. This creates many problems and would cause violations of the ODR in various scenarios, many of which would be presumably ill-formed NDR; Mainly because of the paragraph mentioned by @dyp in the comments, [temp.expl.spec]/6

Moreover, a friend function definition inside a class without an exterior declaration makes this function only invokeable via ADL. Clearly it would be absolutely nonsensical if an explicit specialization is only applicable when the call has associating argument types - again, not to mention the violations of the ODR.

Those and other reasons make such a construct far too complicated too allow, while not being very beneficial: What you can simply do is adding the specialization as a friend, not in any way indicating whether this specialization is instantiated or explicitly specialized.

friend void foo<T>(const T&);

Any explicit specialization can then be added in namespace-scope.

like image 124
Columbo Avatar answered Sep 21 '22 15:09

Columbo