Newsgroup: it.comp.lang.c++
Titolo: Puntatori a funzioni membro e classi

Salve a tutti,
ho cercato di risolvere il mio problema riguardandomi alcuni post scritti in
passato ma nessuno sembra applicarsi perfettamente al mio problema.
Ho implementato una classe C++ la cui struttura è indicativamente la
seguente:
class myMath
{
   public:
      myMath();
      float (myMath::*Sqrt)(float);
  private:
      float _Standard_Sqrt(float);
      float _SSE_Sqrt(float);
      float _3DNOW_Sqrt(float);
}
In pratica, a seconda di alcune caratteristiche della CPU, il costruttore
assegna al puntatore a funzione membro, una delle tre funzioni membro
private; ad. es:
Sqrt = &myMath::_SSE_Sqrt;
Fin qui non ci sono problemi.
I problemi nascono quando devo chiamare il membro puntato dal puntatore
dall'esterno della classe.
Il codice seguente non funziona:
void main(void)
{
  myMath mm;
  float r = mm.*Sqrt(5);
}
Il compilatore ritorna l'errore c3861: identificatore non trovato nemmeno
con una ricerca dipendente dall'argomento. Ho provato altre soluzioni simili
ma il risultato è sempre stato quello dell'errore di compilazione (magari
con codici diversi: c2297 ecc ecc).
Come è possibile far funzionare il tutto?
Come avrete potuto intuire, sfrutto la classe come contenitore di funzioni
matematiche. All'atto dell'inizializzazione il costruttore assegna al
puntatore l'indirizzo della funzione membro ottimizzata per una particolare
tecnologia supportata dalla CPU.
Comunque non so se è una soluzione corretta o conveniente: l'idea iniziale
era quella di non mettere le funzioni in una classe contenitore (non
utilizzando la OOP); certo non avrei avuto questi problemi... :) Esistono
soluzioni comunque OO più semplici?
Ringrazio fin da subito chi mi aiuterà a risolvere questo fastidioso
problema!
Ciao!
Giorgio


    float r = (mm.*mm.Sqrt)(5);
Max
PS: Gli identificatori che iniziano con un '_' seguito da una lettera maiuscola
sono riservati all'implmentatore (del compilatore e della LS). Non usarli.

 ha scritto nel messaggio
news:puE7c.86465$z23.3...@news3.tin.it...

int main()
{
    myMath mm;
    float r = (mm.*myMath::Sqrt)(5);
}
Pero' a me sembrerebbe + semplice una cosa tipo:
class myMath
{
public:
    float sqrt(float f)
    {
        if (this->Sqrt != NULL)
        {
            reeturn (this->*Sqrt)(f);
        } else
        {
        /* gestione dell'errore */
        }
    }
    myMath();
private:
    /*resto della classe come lo hai scritto tu. Adesso anche il puntatore a
membro deve essere privato */
};
int main()
{
    myMath mm;
    float r = mm.sqrt(5.0f);
}

 }
Avrei un'idea. Perche' non implementi una normale funzione e la chiami 
sqrt() e poi lasci a questa fn il compito di chiamare la sqrt giusta? 
Guarda il codice:
class myMath
{
   public:
      float sqrt (float f)   { ptSqrt(f); }
   private:
       float  (*ptSqrt)(float);
}
Durante il costruttore inizializzi ptSqrt alla funzione giusta in modo 
che quando chiami myMath.sqrt() questa automaticamente chiama la fn 
corretta.
Avendo implementato sqrt() nella dichiarazione di classe, questa funzione 
dovrebbe essere messa inline automaticamente dal compilatore evitando 
quindi di chiamare una funzine che chiama una funzione...essendo inline 
dovresti risparmiarti un jump.

 Guarda il codice:
L'idea di lasciare gestire a una funzione generica Sqrt la scelta di quale
funzione specializzata eseguire mi era già passata per la mente ma non so
quanto questo penalizzi la velocità di esecuzione. Ho trovato in GameDev.net
un thread in cui si discuteva di una cosa simile, sempre per una libreria
matematica. In pratica si arrivava alla conclusione di fare una delle 2 cose
seguenti:
1) Generare 3 librerie dinamiche differenti, due contenenti codice
ottimizzato rispettivamente per SSE, per 3DNow! e l'altra conenente chiamate
alle funzioni matematiche standard di C++; linkare quindi la libreria adatta
a run-time;
2) Utilizzare il costrutto switch che risulterebbe molto più veloce del
richiamo delle funzioni appropriate attraverso puntatori. La funzione Sqrt
generica, in questo caso, si presenterebbe nel modo seguente:
float Sqrt(float x)
{
   switch (Cpu_Feature)
   {
      case CPU_FEATURE_SSE:
           return _SSE_Sqrt(x);
      case CPU_FEATURE_3DNOW:
           return _3DNOW_Sqrt(x);
   }
   return _Standard_Sqrt(x);
}
Ovviamente le funzioni specializzate sono private e inline (ho letto di
usare __forceinline, perchè sembra che MSVC non si curi molto della
direttiva inline)
Scarterei a priori la soluzione 1; vorrei che mi forniste qualche commento
sulla II soluzione proposta.
Secondo voi questa soluzione è accettabile? Tenete conto che, per gli
utilizzi a "basso livello" della libreria, sono fondamentali le performance
piuttosto che una lineare e pulita ingegnerizzazione del codice.
Grazie a tutti quelli che mi hanno risposto e che risponderanno a questo
ulteriore quesito!
Ciao!
Giorgio