2016-05-23 36 views
9

L'intestazione Linux <ncurses.h> definisce la funzione meta e la libreria di metaprogrammazione C++ meta inserisce tutto il suo codice nello spazio dei nomi globale meta.Nome collisione tra lo spazio dei nomi della libreria C++ e la funzione C linux

Come posso utilizzare entrambi nello stesso programma C++ (non necessariamente la stessa TU ma sarebbe bello)? C'è un modo per aggirare il nome collision?

mi viene in mente due soluzioni fragili, ma sono facili da rompere:

  • Soluzione A:

    namespace linux { 
    #include <ncurses.h> 
    } // namespace linux 
    using linux::max_align_t; // ncurses assumes it is in the global namespace 
    #include <meta/meta.hpp> 
    

    compila ma probabilmente non riescono a collegare in quanto le ncurses simboli sono attesi nel lo spazio dei nomi globale.

  • Soluzione B:

    #include <ncurses.h> 
    namespace cpp { 
    #include <meta/meta.hpp> 
    } // namespace cpp 
    

    è molto fragile in quanto funziona solo fino a quando la libreria meta non si assume che qualsiasi dei suoi simboli sono nel namespace globale. Cioè, se la biblioteca ha bisogno di disambiguare internamente un simbolo e usa ::meta::symbol_name per quello, questo approccio si interromperà.

+1

L'approccio A non funzionerà, come sapete voi stessi. L'approccio B potrebbe funzionare - puoi provare. Ma prima dovrei cercare di separare queste due librerie in modo che nessuna singola unità di transalione usi entrambe le cose. – SergeyA

+3

Prova a scrivere un wrapper per uno in modo da non includere mai entrambe le intestazioni nella stessa unità di traduzione e sperare che il linker funzioni correttamente. – nwp

+0

@NathanOliver '' ha una funzione chiamata meta, mentre '' ha uno spazio dei nomi chiamato 'meta' all'interno del namespace globale, quindi il nome della funzione si scontra con il nome dello spazio dei nomi. – gnzlbg

risposta

7

vorrei suggerire soluzione C: Isolare il codice in modo che l'uso meta biblioteca e l'uso sono nel ncurses unità di traduzione distinte nel progetto. In questo modo in ogni particolare unità di traduzione non c'è un solo simbolo usato sia come spazio dei nomi che come funzione globale.

+0

Poiché meta è una libreria di sola intestazione, è probabilmente più semplice scrivere un wrapper attorno a '' che include solo questa intestazione nel suo file cpp. – gnzlbg

+0

@gnzlbg Se ti guardi intorno un po 'sono sicuro che ci sono già wrapper in C++ per la libreria ncurses che puoi usare. :) –

+2

@JoachimPileborg non necessario: ncurses include già collegamenti C++ (http://stackoverflow.com/questions/544280/c-wrappers-for-ncurses) – Garf365

1

Sono ragionevolmente certo che né A né B funzioneranno effettivamente, almeno come dato. Hai indicato uno di loro, ma penso che sia il meno probabile dei due. Ci sono due problemi che fondamentalmente sono immagini speculari l'una dell'altra.

Se il codice in ncurses è dichiarata come extern "C" (tipico di molte librerie C che sono stati fatti per lavorare con C++), che li circonda con uno spazio dei nomi non potrà mai funzionare - una dichiarazione extern "C" ignora sostanzialmente spazi dei nomi e dichiara un funzione nel namespace globale. Lo spazio dei nomi non cambierà molto di nulla e avrai ancora una collisione.

Se il contenuto di <ncurses.h> non è dichiarato extern "C", poi si incorrerà nel problema hai citato: la libreria è costruito con funzioni nel namespace globale, ma il codice del client è vedere le definizioni per il codice nel linux namespace. Poiché lo spazio dei nomi influenza il nome storpiato (è così che impedisce una collisione) il tuo codice non sarà in grado di collegarsi. Tutte le funzioni linux::* verranno visualizzate come elementi esterni non risolti.

Per fare questo lavoro, è necessario assicurare che nessuno dei codice della libreria viene dichiarato extern "C", e specificare lo spazio dei nomi all'interno l'intestazione (ei file di origine biblioteca), e ri-compilare la libreria con queste dichiarazioni, quindi la libreria e il suo codice client concordano nello spazio dei nomi in cui risiede quel codice.