2013-07-23 3 views
6

ho passato molto tempo a cercare di capire il motivo per cui la seguente non sarebbe compilare:C++ come proteggersi dalle macro stdio.h

enum IPC_RC {OK, EOF, ERROR, NEW }; 

Il messaggio di errore solo detto qualcosa per l'effetto che wasn' Mi aspetto di vedere una parentesi aperta. Non è stato fino a quando ho provato compilarlo su un compilatore più moderno che ho imparato:

/usr/include/stdio.h:201:13: note: expanded from macro 'EOF' 
#define EOF  (-1) 

Così ho finalmente stato bruciato da una macro! :)

Il mio codice non #include <stdio.h> (Non includo nulla con un suffisso .h), ma chiaramente qualcosa che ho incluso ha comportato l'inclusione di <stdio.h>. C'è un modo (namespace?) Per proteggermi, senza tracciare esattamente dove è stato incluso?

+0

I 'Basta usare un nome diverso, ma quando si tratta di esso, si ca n #undef. – chris

+4

@chris non vorrei '# undef' it. Vorrei comunque usare un nome diverso poiché le macro sono fondamentalmente una sostituzione di testo. – Rapptz

+0

@Rapptz, non lo farei neanche io. – chris

risposta

1

Non conosco una soluzione soddisfacente al problema che descrivi, ma volevo solo condividere un modo per gestire la situazione. Ogni tanto tu (devi) usare un header particolarmente odioso che ridefinisce buona parte della lingua inglese. Le intestazioni X11 di Python.h vengono in mente. Quello che ho finito - e ha funzionato molto bene - è che (di solito dopo aver notato la rottura) avvolgo l'intestazione di terze parti nella mia intestazione e gestisco la brutta situazione.

Per esempio, in progetti che fanno uso dell'interprete Ruby, io di solito non includo ruby.h directory ma piuttosto includere un file ourruby.h che sembra qualcosa di simile:

#ifndef RUBY_OURRUBY_H 
#define RUBY_OURRUBY_H 

// In Ruby 1.9.1, win32.h includes window.h and then redefines some macros 
// which causes warnings. We don't care about those (we cannot fix them). 
#ifdef _MSC_VER 
# pragma warning(push) 
# pragma warning(disable:4005) 
#endif 
#include <ruby.h> 
#ifdef _MSC_VER 
# pragma warning(pop) 
#endif 

// In Ruby 1.8.7.330, win32.h defines various macros which break other code 
#ifdef read 
# undef read 
#endif 
#ifdef close 
# undef close 
#endif 
#ifdef unlink 
# undef unlink 
#endif 
// ... 

#endif // !defined(RUBY_OURRUBY_H) 

In questo modo, I don' Devo occuparmi di ricordare che alcune intestazioni non sono esattamente pulite nello spazio dei nomi.

3

Gli spazi dei nomi non saranno una soluzione perché le macro li ignorano.

in modo da avere due opzioni:

  • sbarazzarsi di quei macro te:

    #ifdef EOF 
    #undef EOF 
    #endif 
    
  • utilizzare un prefisso con i tuoi valori enum:

    enum IPC_RC 
    { 
        IPC_OK, 
        IPC_EOF, 
        IPC_ERROR, 
        IPC_NEW 
    };