Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Neodivert en 19 de Abril de 2009, 09:04:53 PM

Título: Puntero estático a función en plantilla de C++
Publicado por: Neodivert en 19 de Abril de 2009, 09:04:53 PM

Buenas amigos. Estoy desarrollando una plantilla para crear fracciones de cualquier tipo.  Al tratar de implementar un método para eventualmente simplificar dichas fracciones concluí que lo mejor sería disponer de un puntero a dicha función cuyos parámetros fueran el numerador y el denominador y que el programador que usara dicha plantilla le pasara dicha función. También debía tratarse de un puntero / función estática, para evitar tener varias fracciones del mismo tipo pero simplificadas de modo diferente. Después de consultar en varias páginas web y mediante el arcaico pero efectivo método de prueba-error  0:-) lo implementé de la siguiente forma.

cFraccion.cpp

template <class A>
class cFraccion {
    private:
        A Num, Den, Comun;
        static void (* Simplificar)( A& Num, A& Den );

    public:

        ...

};

...

// Función creada por mí para simplificar la fracción en el caso de que contenga números enteros.
inline void Simp( int &Num, int &Den ) ;


Prueba.cpp

#include"cFraccion.cpp"

void Simp( float &a, float &b ){
    a -= 1;  // Simplemente puse esto para comprobar que invocaba a la función correcta. ;-)
}

void Simp( char &a, char &b ){ // (1)
};

template <class A>
void (*cFraccion<A>::Simplificar)( A& Num, A& Den ) = Simp; // (2)

int main(){

    cFraccion<int> A ( 4, 2 );
    cFraccion<float> B ( 2.1, 1 );
    cFraccion<char> C ( 'a', 'b' );

    cout << A << endl
         << B << endl
         << C << endl;
}


El programa compila perfectamente, pero le veo un par de limitaciones:
En (1): Si alguien no desea tener un método para simplificar las fracciones, debe crear una función que no haga nada. Cosa que no veo "elegante".
En (2): Tal como declaro y defino el puntero estático, la función para simplificar tiene que tener siempre el mismo nombre "Simp". Esto en realidad no me "molesta", pero puede que haya una forma que de más "libertad".

Luego la pregunta es: ¿Hay una forma mejor de implementarlo?

¡Gracias!  ;)

P.D. "Por si colaba", probé con


template <class A>
void (*cFraccion<int>::Simplificar)( int& Num, int& Den ) = Simplicar_Enteros; // Renombrando la función obviamente.


pero me lanza un error: "internal compiler error: in output_constant, at varasm.c: 3866

Título: Re: Puntero estático a función en plantilla de C++
Publicado por: Pogacha en 19 de Abril de 2009, 10:09:12 PM
Punteros a funciones en casos extremos de ultima necesidad lease optimizaciones complicadas.

Ya que vas a tener templates usa politicas, o sea:
Citar
template<class T> struct MiSimplificacion { 
   static void Simplificar(T& num, T& den)
  {
    // ACA escribis tu simplificacion
   } 
};

template<class T> struct NoSimplificar { 
   static void Simplificar(T& num, T& den)
  {
  // no hace nada
   } 
};

template<class T, class PoliticaDeSimplificacion = NoSimplificar> Fraccion
{
   T num, dem;
    Simplificar() {  PoliticaDeSimplificacion::Simplificar(num, dem); }
};
 

Fraccion<float>  m; // fracciones con flotantes que no se simplifican nunca

Fraccion<int, MiSimplificacion>  m; // fracciones con enteros que no se simplifican con MiSimplificacion

Libro a leer: Modern C++

Saludos
Título: Re: Puntero estático a función en plantilla de C++
Publicado por: Neodivert en 21 de Abril de 2009, 02:09:24 PM
¡Muchas gracias !  :)

Pero cuando intento escribirlo así:


struct Simplificar_Enteros {
    static void Simplificar( int& Num, int& Den ){
        int Comun;
        if( Num && Den ){
            if( Den < 0 ){
                Num = -Num;
                Den = -Den;
            }
            Comun = mcd( ( ( Num > 0 ) ? Num : - Num ), ( ( Den > 0 ) ? Den : -Den ) );
            Num /= Comun;
            Den /= Comun;
        }
    }
};

template <class A>
struct No_Simplificar {
    static void Simplificar(A& num, A& den){
    }
};

template <class A, class Simplificacion = No_Simplificar>
class cFraccion {
    private:
        A Num, Den, Comun;
        static void Simplificar(){
            Simplificacion::Simplificar( Num, Den );
        }
        ...
};


me arroja el error "No_Simplificar is not a type" en la línea

template <class A, class Simplificacion = No_Simplificar>

¿A qué se debe?  ???

¡Gracias!

P.D. El libro parece interesante, veré si está por la biblioteca de la facultad.  :P
Título: Re: Puntero estático a función en plantilla de C++
Publicado por: Pogacha en 21 de Abril de 2009, 02:22:34 PM
Me falto el <A>
template <class A, class Simplificacion = No_Simplificar<A> >
Título: Re: Puntero estático a función en plantilla de C++
Publicado por: Neodivert en 23 de Abril de 2009, 01:00:56 AM

¡Muchísimas gracias! ¡Solucionado!  ;)