Как обрабатывать развивающееся пространство имен c ++ std :: name?Например: std :: tr1 :: shared_ptr против std :: shared_ptr против boost :: shared_ptr против boost :: tr1 :: shared_ptr - PullRequest
9 голосов
/ 17 августа 2011

Для кода, над которым я сейчас работаю, нам иногда нужно скомпилировать на некоторых старых системах со старыми компиляторами (например, мы запускаем sims на более старом IBM BlueGene / L, контракт поддержки которого диктует какой-то довольно старый компилятор C ++).Сам код использует shared_ptrs, и первоначально был написан для использования std :: tr1 :: shared_ptr.При компиляции на старой машине BlueGene я быстро понял, что у нее нет реализации tr1 ::, и поэтому я переключился на boost :: shared_ptr.Оказывается, есть также повышение :: tr1 :: shared_ptr.Теперь, когда код используется более широко за пределами нашей исследовательской группы, переносимость становится еще более важной.

Какова (?) Лучшая практика для решения подобных проблем развивающихся стандартных библиотек в большихish кодовая база?Я предполагаю, что в новом стандарте C ++ 11 shared_ptr больше не будет находиться в пространстве имен tr1, что добавляет еще один потенциал: std :: shared_ptr, однако я предполагаю, что широко распространенная поддержка этого будет выходить из положения.Я хотел бы использовать последний стандарт, если это возможно, но нужно поддерживать мобильность.Должен ли я просто придерживаться наддува?

Ответы [ 3 ]

9 голосов
/ 17 августа 2011

Чтобы определить, в каком пространстве имен находится shared_ptr, вам нужно что-то вроде autoconf - вот почему был создан autoconf (обнаружение вариаций платформы / компилятора).Вы можете сделать это с помощью:

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.])
])

Повторите для std::tr1::shared_ptr, boost::tr1::shared_ptr и boost::shared_ptr.

Затем вы можете создать файл shared_ptr.hpp, который будет выглядеть примерно так:

#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

... который затем можно использовать как:

ptr::shared_ptr<int> pointer(new int(5));
8 голосов
/ 17 августа 2011

Частично ответ на ваш вопрос

boost::tr1 придумано именно для стандартных реализаций библиотеки, у которых нет tr1. Цитировать документацию от здесь :

Библиотека TR1 обеспечивает реализацию Технического отчета C ++ на стандартных расширениях библиотеки. Эта библиотека сама не реализует компоненты TR1, скорее это тонкая оболочка, которая будет включать в себя ваш реализация TR1 стандартной библиотеки (если она есть), в противном случае она будет включать эквиваленты Boost Library и импортировать их в пространство имен std :: tr1

1 голос
/ 17 августа 2011

Почему бы не провести специальную проверку времени компиляции?Вид:

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

BOOST shared_ptr<...> ...

Вы можете посмотреть в библиотеках буста, у них много кода для определения компилятора / версии.

Подробнее см. в этом вопросе о макросах, особенно этой ссылке: http://predef.sourceforge.net/.

...