Search code examples
c++templatestemplate-specializationspecializationpartial-specialization

Specialized friend function in C++


I have a function template foo that has to perform different computations depending on whether the template parameter is a real or a complex number. In any case, the result will be a real number, e.g. double, even if the template parameter is std::complex<double>. Therefore, my function looks as follows:

template <class S>
struct RealType
{
  typedef S type;
};

template <class S>
struct RealType<std::complex<S> >
{
  typedef S type;
};

template <class S>
class C;

template <class S>
typename RealType<S>::type foo(C<S> &c);

template <class S>
typename RealType<std::complex<S> >::type foo(C<std::complex<S> > &c);

Now foo must be a friend function of the class C, so I made the following declaration:

template <class S>
class C
{
  friend typename RealType<S>::type foo(C<S> &c);
  // ...
};

However, when I instantiate C<std::complex<double> > the compiler says that foo cannot access the private members of c. It works fine for C<double>. Is there any solution to this (that works with C++98)? I understand that foo cannot be a member of C, as this will prevent the partial specialization.

BTW: Is this really a specialization? The signatures of both versions of foo look the same, but in fact they are somewhat different when the real types are plugged in.


Solution

  • Make sure that class C declares foo a friend after foo has been declared.

    You may need to use forward declarations for that:

    template <class S> class C;
    
    // foo declarations here
    
    template <class S> class C 
    { 
        template<class X> friend typename RealType<X>::type foo(C<X> &c); // friend the template
        friend typename RealType<S>::type foo<>(C &c); // friend the specialization
    };