2011-08-17 15 views
9

Dla kodu, nad którym obecnie pracuję, czasami musimy skompilować na niektórych starszych systemach ze starszymi kompilatorami (np. - uruchamiamy simy na starszym IBM BlueGene/L, którego umowa o wsparcie dyktuje dość stary kompilator C++). Sam kod korzysta z shared_ptrs i został pierwotnie napisany w celu użycia std :: tr1 :: shared_ptr. Podczas kompilacji na starym komputerze BlueGene szybko zorientowałem się, że nie ma on implementacji tr1 ::, więc przełączyłem się na boost :: shared_ptr. Okazuje się, że istnieje również boost :: tr1 :: shared_ptr. Teraz, gdy kod jest wykorzystywany szerzej poza naszą grupą badawczą, przenośność staje się jeszcze ważniejsza.Jak radzić sobie z ewoluującym C++ std :: namespace? np: std :: tr1 :: shared_ptr vs. std :: shared_ptr vs. boost :: shared_ptr vs. boost :: tr1 :: shared_ptr

Co to jest (?) Najlepsza praktyka do obsługi tego rodzaju ewoluujących problemów ze standardową biblioteką w wielkiej bazie kodu? Zakładam, że w nowym standardzie C++ 11 shared_ptr nie będzie już w przestrzeni nazw tr1, co dodaje kolejny potencjał: std :: shared_ptr, jednak domyślam się, że powszechne wsparcie dla tego będzie odbiegało. Chciałbym używać najnowszego standardu, jeśli to możliwe, ale muszę zachować przenośność. Czy powinienem po prostu trzymać się dopalacza?

+0

Istnieją już kompilatory gdzie 'std :: shared_ptr' jest dostępny, podobnie jak VC2010 i najnowsze wersje g ++.Jeśli potrzebujesz obsługi wielu różnych kompilatorów, trzymanie się boost jest prawdopodobnie najłatwiejsze. :) – Sven

+0

Tylko dlatego, że shared_ptr zostanie dodane do przestrzeni nazw std :: nie znaczy, że będzie * usunięte * z namespace std :: tr1 ::. Wiem, że gcc/libstdC++ będzie utrzymywało obydwa naprzód. W rzeczywistości jestem pewien, że visual studio będzie takie samo. – emsr

+0

Myślę, że jeśli się rozejrzysz, obsługa std :: shared_ptr jest bardzo szeroka w większości kompilatorów w ciągu ostatnich dwóch lat. Trzymałbym się std :: first, potem szukam std :: tr1 :: następnie spróbuj boost w tej kolejności. – emsr

Odpowiedz

8

Częściowa odpowiedź na swoje pytanie

boost::tr1 jest wymyślona właśnie dla standardowych implementacji bibliotek, które nie mają tr1. Zacytować dokumentację z here:

Biblioteka TR1 zapewnia implementację Raportu C++ Technicznej na standardowej bibliotece Extensions. Ta biblioteka sama w sobie nie implementuje komponentów TR1, a raczej jest cienkim opakowaniem, które będzie zawierać implementację TR1 biblioteki standardowej (jeśli ją posiada), w przeciwnym razie będzie zawierać ekwiwalenty funkcji Boost Library i zaimportować je do standardowej przestrzeni nazw: : tr1

+0

Bardzo dziękuję za cynk - nie miałem pojęcia, że ​​boost :: tr1 jest importowany do std :: tr1. Posiadanie boost :: tr1 ma teraz dla mnie więcej sensu. Twoje zdrowie! – MarkD

1

Dlaczego nie masz specjalnego sprawdzenia czasu kompilacji? Rodzaj:

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

BOOST shared_ptr<...> ... 

Możesz wyszukiwać w bibliotekach doładowań, mają one dużo kodu wykrywania kompilatora/wersji.

Aby uzyskać szczegółowe informacje na temat makr, patrz: this question, szczególnie ten link: http://predef.sourceforge.net/.

+0

Robię podobne z wyjątkiem używać std :: tr1 i std :: zamiast. – emsr

+0

Tak naprawdę robiłem coś takiego, ponieważ było to najłatwiejsze. Kiedy zaczęło się bardziej plątać (na przykład niektóre kompilatory mają zmiany w obsłudze TR1 dla mniejszych wersji), zdecydowałem się po prostu użyć 'std' w kodzie biblioteki i pozwolić użytkownikowi zaadaptować swoje środowisko, on wie o tym lepiej niż ja. –

9

Aby wykryć, w której przestrzeni nazw znajduje się shared_ptr, potrzebujesz czegoś takiego jak autoconf - z tego powodu został utworzony autoconf (wykrywanie odmian platformy/kompilatora). Można to zrobić za pomocą:

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

powtórz dla std::tr1::shared_ptr, boost::tr1::shared_ptr i boost::shared_ptr.

Następnie można utworzyć plik shared_ptr.hpp że jest coś takiego jak:

#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 

..., które można następnie wykorzystać jako:

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

Twój drugi komentarz w przykładzie autokonf powinien zostać odwrócony – Attila