EN VI

C++ - why explicit specialization of a friend function is allowed?

2024-03-10 23:00:06
C++ - why explicit specialization of a friend function is allowed?

As a general rule, explicit specialization is allowed on a namespace scope. The following code:

template<typename T>
class B {
        template<typename U> void test(T) {};
        template<> void test(int) {};
};

make g++ produce the following error: error: explicit specialization in non-namespace scope

At the same time, friend function template specialization is one of two possible ways to make friend function templates work inside class templates. The following code works like a charm:

template<typename T>
class B; 

template<typename T>
void test(B<T>);

template<typename T>
class B {
        friend void test<>(B<T>);
};

At the same time, the following does not compile, giving the same error as for the Snippet one:

template<typename T>
class B {
        template<typename U> friend void test(U);
        template<>friend void test<B<T>>(B<T>);
};

My questions are:

  1. Why friends are getting this kind of special treatment (would appreciate a reference to a standard);
  2. What is this wicked sintax for full specialization anyways? Snippet: friend void test<>(B<T>);

EDIT 1 Fixed syntax errors in snippet 1.

Solution:

Assuming you fix the obvious syntax errors in your example:

Explicit specializations of member function templates are also allowed in class scope. This has been clarified a long time ago, but it is a defect report that GCC has never implemented (so far), see GCC bug report.

However, a friend declaration may not declare an explicit or partial specialization. Doing that isn't really sensible, because the function (template) declared by the friend declaration belongs to the enclosing namespace scope, not the class scope.

As you showed, it is already possible to friend a specific specialization of a function template. It doesn't matter to the friend declaration whether or not the specialization is declared as an explicit specialization, so there is no reason to allow it. You can declare the explicit specialization of the function template later at namespace scope, where it usually belongs for a non-member function template.

And while

friend void test<>(B<T>);

declares a specific specialization of the function template test to be a friend of the class, it isn't an explicit specialization declaration and doesn't declare that specialization of the function to be explicitly-specialized. The declaration only makes the function specialization a friend, but the primary template will still be used to implicitly instantiate a definition for that specialization.

On the other hand an explicit specialization declaration declares that no implicit instantiation from the primary template should be used for that function template specialization, but that instead the corresponding explicit specialization definition for that function template specialization should be used.

An explicit specialization can be clearly identified by its template head being exactly template<>, no other declaration is an explicit specialization and no explicit specialization looks different.

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login