Domanda

ho voluto verificare che typeid viene valutata al momento della compilazione quando viene utilizzato con un nome del tipo (cioè typeid (int), typeid (std :: string) ...).

Per fare ciò, ho ripetuto in un ciclo confronto di due chiamate typeid, e compilato con ottimizzazioni abilitato, per vedere se il compilatore semplificato loop (osservando il tempo di esecuzione che è 1us quando semplifica invece di 160ms quando lo fa non è).

E ottengo risultati strani, perché a volte il compilatore semplifica il codice, e, a volte non è così. Io uso g ++ (ho provato diverse versioni 4.x), ed ecco il programma:

#include <iostream>
#include <typeinfo>
#include <time.h>

class DisplayData {};

class RobotDisplay: public DisplayData {};
class SensorDisplay: public DisplayData {};

class RobotQt {};
class SensorQt {};

timespec tp1, tp2;
const int n = 1000000000;

int main()
{
    int avg = 0;
    clock_gettime(CLOCK_REALTIME, &tp1);
    for(int i = 0; i < n; ++i)
    {
//      if (typeid(RobotQt) == typeid(RobotDisplay))    // (1) compile time
//      if (typeid(SensorQt) == typeid(SensorDisplay))  // (2) compile time
        if (typeid(RobotQt) == typeid(RobotDisplay) || 
            typeid(SensorQt) == typeid(SensorDisplay))    // (3) not compile time ???!!!
            avg++;
        else
            avg--;
    }
    clock_gettime(CLOCK_REALTIME, &tp2);
    std::cout << "time (" << avg << "): " << 
        (tp2.tv_sec-tp1.tv_sec)*1000000000+(tp2.tv_nsec-tp1.tv_nsec) << 
        " ns" << std::endl;
}

Le condizioni in cui appaiono questo problema non sono chiare, ma:
  - se non v'è alcuna eredità in questione, non è un problema (il tempo sempre di compilazione)
  - se faccio un solo confronto, nessun problema
  - il problema appare solo solo con una disgiunzione di confronti, se tutti i termini sono false

Quindi c'è qualcosa che non ho avuto con come funziona TypeId (è sempre dovrebbero essere valutati al momento della compilazione quando viene utilizzato con nomi di tipo?) O possono essere questo un bug gcc nella valutazione o di ottimizzazione?

A proposito di contesto, ho rintracciato il problema a questo esempio molto semplificato, ma il mio obiettivo è quello di utilizzare typeid con tipi di modello (come parziale funzione di modello di specializzazione non è possibile).

Grazie per il vostro aiuto!

È stato utile?

Soluzione

Io non so davvero la risposta alla tua domanda, ma se si utilizza is_same <> metafunction invece di typeid si potrebbe ottenere risultati più desiderabili. Anche se non si ha accesso a questo metafunction, è molto facile scrivere una:


template < typename T1, typename T2 >
struct is_same
{
  enum { value = false }; // is_same represents a bool.
  typedef is_same<T1,T2> type; // to qualify as a metafunction.
};

template < typename T >
struct is_same
{
  enum { value = true };
  typedef is_same<T,T> type;
};

Altri suggerimenti

typeid è parte del meccanismo runtime identificazione tipo, che suggerisce ciò è utile per: è l'utilizzo principale è identificare il tipo dinamico di un puntatore / riferimento a una classe di base in fase di esecuzione. Quando i tipi sono staticamente noti al momento della compilazione, non è necessario per "individuare" loro come sai già quello che sono.

Nell'esempio, non c'è nulla da individuare in fase di esecuzione, però, ma i risultati non sono in alcun modo utile al momento della compilazione (typeid non può apparire in const-espressioni, che è quello che serve per il modello metaprogrammazione).

Per questo ho anche raccomandare is_same

Per qualsiasi tipo T , se T è polimorfico, il compilatore è tenuto a valutare la roba typeid in fase di esecuzione. Se T non è polimorfica, il compilatore è tenuto a valutare la roba typeid in fase di compilazione. Tuttavia, non riesco a trovare il riferimento rilevante nel C ++ progetto (n3000.pdf) per esso.

Infatti, in uno dei progetti che ho lavorato su, questo trucco è stato utilizzato per trovare se una classe era polimorfica in fase di esecuzione .

template <class T>  
bool isPolymorphic() {  
    bool answer=false; 
    T *t = new T(); 
    typeid(answer=true,*t);  
    delete t; 
    return answer;  
} 

Avevo chiesto una questione connessa qui su SO qualche mese fa .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top