No sé si aún lo necesites, pero si lo mueven al subforo correcto igual a alguien le sirve después. Antes que nada, el mensaje de arriba, que parece ser copy/paste de ChatGPT-3, es un completo disparate, así que mejor ignorarlo.
Primero, ¿estás seguro de que copiaste bien esto?
Código
friend typename RealType<S>::type foo(C<S> &c);
porque ahí estás declarando como amiga una función normal (no plantilla), que además va a tener precedencia sobre las que declaraste (que son plantillas), así que te debería dar error de enlazado. Si dices que te funciona bien para C<double>, supongo que más bien la declaraste así:
Código
friend typename RealType<S>::type foo<S>(C<S> &c);
que es la forma correcta. Y ahí sí tienes el problema que comentas, porque con estas declaraciones:
Código
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);
nota que el parámetro de tipo para la plantilla es S en las dos. En ningún caso es std::complex<S>. Lo que el compilador hará será sobrecargar la función foo<S>: una versión recibe un parámetro de tipo C<S>&, y la otra uno de tipo C<std::complex<S> >&. Esto responde a tu otra pregunta: no, no es especialización sino sobrecarga.
Por lo tanto, si tienes algo como esto:
Código
C<double> c_real; C<std::complex<double> > c_complejo; foo(c_real); foo(c_complejo)
las funciones que se generan son (omito los tipos de retorno por legibilidad):
Código
foo<double>(C<double>& c); foo<double>(C<std::complex<double> >& c);
nota que las dos "se llaman" foo<double>. Sin embargo, en la clase C:
Código
template <class S> class C { friend typename RealType<S>::type foo<S>(C<S> &c); // ... };
si declaras una variable C<std::complex<double> >, entonces, en lo que respecta a C, S es igual a std::complex<double>. Por lo tanto, lo que se estaría declarando como amiga es una hipotética función:
Código
foo<std::complex<double> >(C<std::complex<double> >& c);
pero como te dije, la función que declaraste se genera como:
Código
foo<double>(C<std::complex<double> >& c);
que no es amiga de C, y de ahí el error. No sé exactamente qué quieras lograr, pero posiblemente esto sea lo que buscas:
Código
template <class S> class C { friend typename RealType<S>::type foo<typename RealType<S>::type>(C<S>& c); };
Así, en ambos casos se declararía como amiga foo<double> (siquiendo con los ejemplos), en su versión sobrecargada de acuerdo al tipo de C.