2011-08-17 14 views
9

Para el código en el que estoy trabajando actualmente, a veces necesitamos compilar en algunos sistemas anteriores con compiladores más antiguos (por ejemplo, ejecutamos sims en un IBM BlueGene/L antiguo, cuyo contrato de soporte dicta algún compilador de C++ bastante antiguo). El código hace uso de shared_ptrs, y fue escrito originalmente para usar std :: tr1 :: shared_ptr. Al compilar en la máquina antigua de BlueGene, me di cuenta rápidamente de que no tenía una implementación tr1 ::, así que cambié a boost :: shared_ptr. Resulta que también hay un impulso :: tr1 :: shared_ptr. Ahora que el código se está utilizando más ampliamente fuera de nuestro grupo de investigación, la portabilidad es cada vez más importante.Cómo manejar la evolución de C++ std :: namespace? por ejemplo: std :: tr1 :: shared_ptr vs. std :: shared_ptr vs. boost :: shared_ptr vs. boost :: tr1 :: shared_ptr

¿Cuál es la (mejor) práctica para manejar este tipo de problemas de biblioteca estándar en evolución en una base de código grande? Supongo que en el nuevo estándar C++ 11, shared_ptr ya no estará en el espacio de nombres tr1, lo que agrega otro potencial: std :: shared_ptr; sin embargo, supongo que el soporte generalizado para esto estará muy lejos. Me gustaría utilizar el último estándar si es posible, pero necesito mantener la portabilidad. ¿Debo seguir con el impulso?

+0

Ya hay compiladores donde 'std :: shared_ptr' está disponible, como VC2010 y versiones recientes de g ++.Si necesita soportar una multitud de compiladores diferentes, seguir con el impulso es probablemente el más fácil. :) – Sven

+0

Solo porque shared_ptr se agregará al espacio de nombres std :: no significa que será * eliminado * del espacio de nombres std :: tr1 ::. Sé que gcc/libstdC++ mantendrá ambos en el futuro. De hecho, estoy seguro de que el estudio visual será el mismo. – emsr

+0

Creo que si miras a tu alrededor, el soporte para std :: shared_ptr es muy amplio en la mayoría de los compiladores en los últimos dos años como mínimo. Me quedaría con std :: first, luego buscaré std :: tr1 :: luego probaré boost en ese orden. – emsr

Respuesta

8

parcial respuesta a su pregunta

boost::tr1 se inventó precisamente para las implementaciones de la biblioteca estándar que no tienen un tr1. Para citar la documentación de here:

La biblioteca TR1 proporciona una implementación del Informe Técnico C++ estándar en la biblioteca de extensiones. Esta biblioteca no implementa los componentes TR1 , sino que es una envoltura delgada que incluirá la implementación TR1 de la biblioteca estándar (si tiene una); de lo contrario, incluirá los equivalentes de la Biblioteca Boost e importará a namespace std: : tr1

+0

Muchas gracias por la sugerencia, no tenía idea de que boost :: tr1 importó a std :: tr1. Tener boost :: tr1 ahora tiene mucho más sentido para mí. ¡Aclamaciones! – MarkD

1

¿Por qué no tener alguna comprobación de tiempo de compilación especial? Tipo de:

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

BOOST shared_ptr<...> ... 

Puede buscar en las bibliotecas de impulso, tienen un montón de código de compilación/detección de versión.

Consulte this question para obtener detalles sobre las macros, especialmente este enlace: http://predef.sourceforge.net/.

+0

Lo hago de forma similar, excepto que utilizo std :: tr1 y std :: en su lugar. – emsr

+0

En realidad solía hacer algo así porque era lo más fácil de hacer. Cuando comenzó a enredarse más (algunos compiladores tienen cambios en el soporte de TR1 en versiones menores, por ejemplo) decidí simplemente usar 'std' en el código de la biblioteca y dejar que el usuario adapte su entorno, él lo sabe mejor que yo. –

9

Para detectar en qué espacio de nombres está shared_ptr, necesita algo como autoconf: esta es la razón por la que se creó autoconf (detección de variaciones de plataforma/compilador). Usted puede hacer esto 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.]) 
]) 

Repetir para std::tr1::shared_ptr, boost::tr1::shared_ptr y boost::shared_ptr.

A continuación, puede crear un archivo de shared_ptr.hpp que es algo así como:

#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 

... que luego se puede utilizar como:

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

Su segundo comentario en el ejemplo de autoconf debe invertirse – Attila

Cuestiones relacionadas