2011-08-17 32 views
9

Per il codice al momento sto lavorando, a volte abbiamo bisogno di compilare su alcuni sistemi meno recenti con compilatori più vecchi (ad esempio, eseguiamo sim su un IBM BlueGene/L precedente, il cui contratto di supporto impone un compilatore C++ piuttosto vecchio). Il codice stesso usa shared_ptrs, e fu originariamente scritto per usare std :: tr1 :: shared_ptr. Durante la compilazione sulla vecchia macchina BlueGene, mi sono subito reso conto che non ha una tr1 :: implementation, quindi sono passato a boost :: shared_ptr. Risulta anche un boost :: tr1 :: shared_ptr. Ora che il codice viene utilizzato più ampiamente al di fuori del nostro gruppo di ricerca, la portabilità sta diventando ancora più importante.Come gestire l'evoluto C++ std :: namespace? es: std :: tr1 :: shared_ptr vs. std :: shared_ptr vs boost :: shared_ptr vs boost :: tr1 :: shared_ptr

Che cos'è una (la?) Migliore pratica per gestire questi tipi di problemi di libreria standard in evoluzione in una base di codice di grandi dimensioni? Sto assumendo che nel nuovo standard C++ 11, shared_ptr non sarà più nel namespace tr1, che aggiunge un altro potenziale: std :: shared_ptr, tuttavia immagino che un supporto diffuso per questo sarà un modo diverso. Mi piacerebbe utilizzare l'ultimo standard, se possibile, ma devo mantenere la portabilità. Dovrei limitarmi ad aumentare?

+0

Ci sono già compilatori dove 'std :: shared_ptr' è disponibile, come VC2010 e versioni recenti di g ++.Se hai bisogno di supportare una moltitudine di compilatori diversi, il potenziamento è probabilmente il più semplice. :) – Sven

+0

Solo perché shared_ptr verrà aggiunto allo spazio dei nomi std :: non significa che sarà * rimosso * dallo spazio dei nomi std :: tr1 ::. So che gcc/libstdC++ manterrà entrambi andando avanti. In effetti, sono sicuro che lo studio visivo sarà lo stesso. – emsr

+0

Penso che se ti guardi intorno, il supporto per std :: shared_ptr è molto ampio nella maggior parte dei compilatori negli ultimi due anni almeno. Rimanerei con std :: first, quindi cerca std :: tr1 :: quindi prova ad aumentare in questo ordine. – emsr

risposta

8

parziale risposta alla tua domanda

boost::tr1 è inventato proprio per le implementazioni di libreria standard che non hanno un tr1. Per citare la documentazione da here:

La libreria TR1 fornisce un'implementazione del Rapporto C++ tecnico su Standard Library Extensions. Questa libreria non implementa direttamente i componenti TR1 , piuttosto è un involucro sottile che includerà l'implementazione TR1 della libreria standard (se ne ha uno), altrimenti lo includerà gli equivalenti della libreria Boost e li importerà nello spazio dei nomi std: : tr1

+0

Grazie mille per il suggerimento- non avevo idea che boost :: tr1 importato in std :: tr1. Avere boost :: tr1 ora ha molto più senso per me. Saluti! – MarkD

1

Perché non avere un controllo speciale del tempo di compilazione? Tipo di:

#if __GNUC__ > 3 
    #define BOOST boost:: 
#else 
    #define BOOST boost::tr1:: 
#endif 

BOOST shared_ptr<...> ... 

È possibile cercare nelle librerie di boost, hanno un sacco di codice di compilazione/rilevamento della versione.

Vedere this question per dettagli sui macro, in particolare questo collegamento: http://predef.sourceforge.net/.

+0

Faccio lo stesso, tranne che io uso std :: tr1 e std :: invece. – emsr

+0

In realtà ero abituato a fare qualcosa del genere perché era la cosa più facile da fare. Quando ha iniziato ad essere più intricato (alcuni compilatori hanno modifiche nel supporto TR1 su versioni minori, ad esempio) ho deciso di usare semplicemente 'std' nel codice della libreria e lasciare che l'utente adattare il suo ambiente, lo conosce meglio di me. –

9

Per individuare lo spazio dei nomi in cui è condiviso shared_ptr, è necessario qualcosa come autoconf - questo è il motivo per cui è stato creato autoconf (rilevamento delle variazioni di piattaforma/compilatore). Si può fare questo con:

AC_LANG(C++) 

AC_MSG_CHECKING([for std::shared_ptr]) 
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
    [[#include <memory>]] 
    [[std::shared_ptr<int> have_shared_ptr;]]) 
], [ 
    AC_MSG_RESULT([yes]) 
    AC_DEFINE_UNQUOTED([HAVE_STD_SHARED_PTR], 1, [Define to 1 if you have the `std::shared_ptr' class.]) 
], [ 
    AC_MSG_RESULT([no]) 
    AC_DEFINE_UNQUOTED([HAVE_STD_SHARED_PTR], 0, [Define to 1 if you have the `std::shared_ptr' class.]) 
]) 

Ripetere l'operazione per std::tr1::shared_ptr, boost::tr1::shared_ptr e boost::shared_ptr.

È quindi possibile creare un file shared_ptr.hpp che è qualcosa di simile:

#include <config.h> 

#if defined(HAVE_STD_SHARED_PTR) 
    namespace ptr = std; 
#elif defined(HAVE_STD_TR1_SHARED_PTR) 
    namespace ptr = std::tr1; 
#elif defined(HAVE_BOOST_SHARED_PTR) 
    namespace ptr = boost; 
#elif defined(HAVE_BOOST_TR1_SHARED_PTR) 
    namespace ptr = boost::tr1; 
#else 
# error No shared_ptr found. 
#endif 

... che è quindi possibile utilizzare come:

ptr::shared_ptr<int> pointer(new int(5)); 
+1

Il tuo secondo commento nell'esempio di autoconf dovrebbe essere invertito – Attila

Problemi correlati