An explicit specialization cannot be a friend declaration
Asked Answered
S

1

8

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?

Sisk answered 4/1, 2015 at 15:35 Comment(5)
gcc reports explicit specialization in non-namespace scope 'struct A<T>' and template-id 'foo<T>' in declaration of primary template for the given code.Osuna
sorry I copy paste from another sourceSisk
Explicit specializations prevent implicit instantiation. Every time you instantiate A for a new set of template arguments, you'd add another explicit specialization of foo. It is ill-formed, No Diagnostic Required, to add that specialization if foo has already been implicitly instantiated for the same template arguments [temp.expl.spec]/6.Clubfoot
@Clubfoot if I understand clearly your comment, it is true for every function template specialization in class template, not only for friends? but compile errors are about friend function specialization. I think there is something special for friends, besides mentioned in your commentSisk
This is true for any kind of template (implicit instantiation before explicit specialization with the same template arguments is ill-formed, NDR). The way new explicit specializations would be added by the code you've shown however make it very likely for such violations to occur, since a) the new specializations would be added implicitly and b) in another scope than the primary template.Clubfoot
C
7

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.

Cornea answered 4/1, 2015 at 16:29 Comment(3)
Or you could overload, by defining a non-template friend function inside.Clubfoot
For completeness, a friend function definition inside a class does generally allow the function to be invoked without ADL, just not using the in-class declaration. As long as an out-of-class declaration is available, it's fine, so: struct S { friend void f() { } } void f(); int main() { f(); } is perfectly valid. But, explicit template specialisations need those explicit specialisations to be declared whenever they are used, so an in-class declaration would not be good enough.Piecemeal
@Cornea Thanks for answer but could you please explain ADL case more clearly, I don't understand the problem. If function template specialization defined in class then it should take an argument of the class or a class derived from that, as ADL mechanism should work. So what is the problem with template specialization definition with such(class or derived) argument?Sisk

© 2022 - 2024 — McMap. All rights reserved.