2011-01-20 15 views
18

Sto provando a generare il nome del file incluso nella macro. Questo dovrebbe essere legale in C++:Genera il nome del file incluso in una macro

#define INCLUDE_FILE "module_impl_win.hpp" 
#include INCLUDE_FILE 

questo funziona bene, ma non appena provo a nome file generato è failes compilare

#define INCLUDE_FILE(M) M##"_impl_win.hpp" 
#include INCLUDE_FILE("module") 

In realtà mi dà avvertimento sul MSVC2010

avviso C4067: gettoni inaspettate seguente direttiva del preprocessore - previsto un Newlin

ma non include il file.

Qual è il problema? Come posso liberarmene?

risposta

18

Lo farei utilizzando una macro di quotazione dell'assistente. Qualcosa di simile a questo vi darà ciò che si vuole:

#define QUOTEME(M)  #M 
#define INCLUDE_FILE(M) QUOTEME(M##_impl_win.hpp) 

#include INCLUDE_FILE(module) 
+1

Devi stare attento con questo approccio.'_impl_win' è un token identificatore e poiché inizia con un trattino basso (e si trova nel namespace della macro), è riservato all'implementazione. Si dovrebbe rompere il '_' principale e concatenarlo separatamente, anche se in cima alla mia testa non sono sicuro di come farlo qui poiché' _' stesso è un identificatore riservato. –

+1

BTW, quanto è portatile? – ledokol

+0

@James McNellis: Standard riserva solo nomi con un trattino basso seguito da caratteri maiuscoli (o nomi contenenti doppio trattino basso). Non so perché Sutter consiglia di evitare l'uso del carattere di sottolineatura ovunque .. – ledokol

3

Il problema è che alla fine il codice sarebbe simile a questa:

#include "module""_impl_win.hpp" 

Questo genera lo stesso avviso e di errore si sta vedendo, ma in un modo un po 'più evidente.

Mentre il compilatore accetta tale sintassi, il preprocessore no.

Non ho un suggerimento per fare quello che stai cercando di fare il lavoro. Personalmente non vorrei usare quel tipo di macro poiché rende più difficile la navigazione visiva del codice e probabilmente impedirebbe a molti editor di navigare velocemente nel codice.

+0

Grazie, non sapevo che concatena stringhe del genere. Immagina che ci siano centinaia di file che includono intestazioni specifiche della piattaforma con #ifdef ... #endif. Se domani aggiungerò il supporto per un'altra piattaforma, avrei bisogno di modificare tutti questi file invece di modificare una macro e aggiungere file di implementazione specifici della piattaforma. È triste – ledokol

+0

@ledokol: Perché la funzionalità specifica della piattaforma non può essere suddivisa in intestazioni separate e file di origine che non sono inclusi altrove? Dovrebbe essere facile consolidare le funzionalità specifiche della piattaforma e della piattaforma in un insieme relativamente piccolo di file. –

+0

Intendi perché PIMPL non viene utilizzato per separare il codice specifico della piattaforma? Beh, non può essere usato ovunque. Esistono molte classi di modelli che richiedono la dichiarazione della classe di implementazione specifica della piattaforma. Quindi devo dividerlo per i file di intestazione e implementazione. – ledokol

3

è anche possibile utilizzare Boost preprocessore, specialmente i BOOST_PP_STRINGIZE/BOOST_PP_CAT macro:

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/stringize.hpp> 

#define INCLUDE_FILE(M) BOOST_PP_STRINGIZE(BOOST_PP_CAT(M, _impl_win.hpp)) 

// expands to: #include "module_impl_win.hpp" 
#include INCLUDE_FILE(module) 

(cfr C Macro - DynamiC#include)

Si noti che questo soffre dello stesso problema della risposta di @ Andrew (leading underscore = riservato identificatore).

Problemi correlati