elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Como proteger una cartera - billetera de Bitcoin


+  Foro de elhacker.net
|-+  Foros Generales
| |-+  Dudas Generales (Moderador: engel lex)
| | |-+  Función de amigo en C ++
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Función de amigo en C ++  (Leído 2,051 veces)
adhar2

Desconectado Desconectado

Mensajes: 5


Ver Perfil
Función de amigo en C ++
« en: 22 Marzo 2023, 09:04 am »

Tengo una plantilla de función foo que debe realizar varios cálculos en función de si el parámetro de la plantilla es real o complejo. Incluso si el argumento de la plantilla es std::complexdouble>, el resultado siempre será un número real, como double. Como resultado, mi función es la siguiente:

Código:
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);

Ahora foo debe ser una función amiga de la clase C, así que hice la siguiente declaración:

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

Sin embargo, cuando creo Cstd::complexdouble> >, el compilador se queja de que foo no puede acceder a los miembros secretos de c. Eso funciona perfectamente con Cdouble> si sigues esta documentación. ¿Hay alguna solución (que funcione con C++ 98) para esto? Me doy cuenta de que foo no puede ser miembro de C ya que no permitiría la especialización parcial.
¿Es esto, por cierto, una especialización? Las firmas de ambas versiones de foo parecen idénticas, pero cambian un poco cuando se ingresan los tipos reales.


« Última modificación: 26 Septiembre 2023, 04:40 am por MCKSys Argentina » En línea

LlopoRobot

Desconectado Desconectado

Mensajes: 116


Un instante, una mente al unísono


Ver Perfil
Re: Función de amigo en C ++
« Respuesta #1 en: 1 Abril 2023, 08:46 am »

Sí, esto es una especialización de plantilla. En este caso, la especialización se produce para el caso en que el tipo de plantilla es std::complex<S>.

El problema que estás enfrentando es que la amistad no se hereda, lo que significa que si tienes una clase derivada de C y intentas llamar a la función foo desde la clase derivada, el compilador no permitirá el acceso a los miembros privados de la clase base. Sin embargo, hay una solución para este problema.

En lugar de hacer que foo sea un amigo de C, puedes hacer que C sea un amigo de foo. Esto permitirá que la función foo acceda a los miembros privados de C sin importar si C es una clase base o una clase derivada. Aquí está cómo se vería el código:

Código:
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);

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

Tenga en cuenta que el <> después de foo indica que la amistad se aplica a todas las especializaciones de la función foo. También tenga en cuenta que esto debería funcionar en C++ 98 y versiones posteriores.

Espero que esto ayude a resolver su problema.


En línea

I'm woman baby. Can't you tell?
RayR

Desconectado Desconectado

Mensajes: 243


Ver Perfil
Re: Función de amigo en C ++
« Respuesta #2 en: 4 Abril 2023, 18:04 pm »

Nota: esto debería ir en el subforo de C++. Aquí difícilmente lo van a ver los foreros que programan en C++. Yo lo vi porque me salió la respuesta de arriba en "mensajes recientes".

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
  1. 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
  1. 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
  1. template <class S>
  2. typename RealType<S>::type foo(C<S> &c);
  3.  
  4. template <class S>
  5. 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
  1. C<double> c_real;
  2. C<std::complex<double> > c_complejo;
  3. foo(c_real);
  4. foo(c_complejo)

las funciones que se generan son (omito los tipos de retorno por legibilidad):

Código
  1. foo<double>(C<double>& c);
  2. foo<double>(C<std::complex<double> >& c);

nota que las dos "se llaman" foo<double>. Sin embargo, en la clase C:

Código
  1. template <class S>
  2. class C
  3. {
  4.  friend typename RealType<S>::type foo<S>(C<S> &c);
  5.  // ...
  6. };

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
  1. foo<std::complex<double> >(C<std::complex<double> >& c);

pero como te dije, la función que declaraste se genera como:

Código
  1. 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
  1. template <class S>
  2. class C
  3. {
  4. friend typename RealType<S>::type foo<typename RealType<S>::type>(C<S>& c);
  5. };

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.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Un amigo me vende PSP « 1 2 »
Juegos y Consolas
anonimo12121 14 7,637 Último mensaje 21 Marzo 2011, 14:56 pm
por TheInfinityJoker
Amigo Batchero « 1 2 3 4 5 »
Scripting
leogtz 41 20,516 Último mensaje 14 Febrero 2013, 14:14 pm
por Eleкtro
El teclado es tu amigo
Hardware
dac 2 2,383 Último mensaje 5 Diciembre 2014, 17:01 pm
por dac
Problema de un amigo
Seguridad
Docken 6 3,140 Último mensaje 14 Enero 2015, 15:06 pm
por Docken
Amigo invisible
Foro Libre
Baal_30 4 2,312 Último mensaje 27 Agosto 2015, 16:24 pm
por Ori-chan
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines