Domanda

Si può rimuovere tutte le chiamate al printf() utilizzando #define printf. Che cosa succede se ho un sacco di stampe di debug come std::cout << x << endl;? Come posso passare rapidamente fuori dichiarazioni cout << in un singolo file utilizzando preprocessore?

È stato utile?

Soluzione

NullStream può essere una buona soluzione se siete alla ricerca di qualcosa di veloce che rimuove istruzioni di debug. Tuttavia mi sento di raccomandare la creazione di una classe per il debug, che può essere espansa come necessario quando è necessaria una maggiore funzionalità di debug:

class MyDebug
{
    std::ostream & stream;
  public:
    MyDebug(std::ostream & s) : stream(s) {}
#ifdef NDEBUG
    template<typename T>
    MyDebug & operator<<(T& item)
    {
      stream << item;
      return *this;
    }
#else
    template<typename T>
    MyDebug & operator<<(T&)
    {
      return *this;
    }
#endif
};

Questa è una semplice configurazione che consente di fare quello che vuoi inizialmente, in più ha il vantaggio di lasciare che si aggiunge funzionalità quali i livelli di debug, ecc ..

Aggiornamento: Ora, poiché i manipolatori sono implementate come funzioni, se si desidera accettare manipolatori così (endl) è possibile aggiungere:

MyDebug & operator<<(std::ostream & (*pf)(std::ostream&))
{
  stream << pf;
  return *this;
}

E per tutti i tipi di manipolatore (in modo che non c'è bisogno di sovraccaricare per tutti i tipi di manipolatore):

template<typename R, typename P>
MyDebug & operator<<(R & (*pf)(P &))
{
  stream << pf;
  return *this;
}

Fate attenzione con quest'ultimo, perché che anche accettare funzioni regolari puntatori.

Altri suggerimenti

"staccare la spina" già detto, la soluzione rapida è un flusso do-nothing. Ci sono implementazioni meglio però:

class NullStream {
    public:
    NullStream() { }
    template<typename T> NullStream& operator<<(T const&) { return *this; }
};

Hai ancora un leggero problema con std::cout dato che è una sequenza di tre gettoni, e davvero non si vuole ridefinire std o cout singolarmente. Una soluzione semplice è

#ifdef NDEBUG
    #define COUT std::cout
#else
    #define COUT NullStream()
#endif

COUT << "Hello, world" << std::endl;

Come principio generale, la registrazione su stdout dovrebbe essere evitato -. Molto meglio registro in un file di log, e quindi è possibile utilizzare strumenti di configurazione standard per modificare i livelli di log, o spegnerlo del tutto

Solo il mio $ 0.02 .....

Sostituire le sue dichiarazioni di output di debug con qualcosa di simile:

IFDBG(cout << result << endl);

Quindi è possibile definire le macro di conseguenza:

#ifdef DEBUG
#  define IFDBG(x) x
#else
#  define IFDBG(x)
#endif

Probabilmente si può fare un hack preprocessore che definisce una nuova classe di flusso simile, con un'istanza denominata cerr, che proprio non fa nulla. Se siete davvero fortunati, il compilatore vedrà che la funzione non fa nulla, e ottimizzare le chiamate operator<<() fuori.

Qualcosa di simile

class NullStream
{
public:
  NullStream();

  NullStream& operator<<(const std::string& text) { return *this; }
  // And operators for other types, too
}
static NullStream cerr;

Questo è abbastanza l'hack, però, è (di gran lunga) meglio passare attraverso la vostra fonte e aggiungere il supporto adeguato per la registrazione.

Definisci questa macro:

#ifdef DEBUG
    #define MY_LOG std::cout
#else
    #define MY_LOG if(false) std::cout
#endif

Questa macro vantaggio è in ottimizzazione del compilatore

  

Se le espressioni poste all'interno di quelle FI sono costante e determinabile al momento della compilazione , allora si può essere quasi sicuri che il compilatore li ha già rimosso fuori il codice per voi ...    https://stackoverflow.com/a/14657645/5052296

La definizione di una macro che sostituisce cout non è qualcosa che si dovrebbe caricare il tuo VCS, ma se lo fai e basta temporaneamente durante il debug, penso che serve il suo posto. Così si può semplicemente sostituire cout da ostream(0) come

#ifdef NDEBUG
#define cout ostream(0).flush()
#endif

In questo modo, funziona sia con std::cout e cout pianura, e ostream è disponibile quando compresi <iostream>. Scrivendo in un ostream(0) è un no-op. La funzione di chiamata flush è fatto in modo da ottenere un riferimento non const ad esso (in modo che si lega anche al operator<< non membro che viene utilizzato per l'uscita std::string e altri). Come il suo tipo è ostream, dovrebbe comportarsi esattamente come cout.

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