2012-05-23 12 views
45

Jeśli masz jakiś kod, w którym chciałbym używać rozszerzeń C++ 11x w maksymalnym możliwym stopniu, ale jeśli nie jest to wspierane, skorzystaj z opcji zastępczej. Obecnie wersja OSX GCC i kompilator VisualC ma niewiele ma wsparcie dla C++ 11x, więc używam:Czy istnieje dyrektywa preprocesora do wykrywania obsługi C++ 11x?

#if (defined(__APPLE__) || (defined(_WIN32))) 
    ...fallback code without C++11x ... 
#else 
    ... code using C++11x ... 
#endif 

I to działa, ale nie jest to słuszne, zwłaszcza od gcc kompilator w systemie MacPorts DOES obsługuje C++ 11x.

Czy istnieje makro typu #define C11X_SUPPORTED? Być może coś tylko GCC ma?

+3

Problem polega na tym, że GCC nie obsługuje jeszcze w pełni C++ 11, więc to naprawdę zależy od funkcji, których chcesz użyć. – juanchopanza

+4

przyspieszy pracę: http://www.boost.org/doc/libs/1_49_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_c__11_features_not_supported? – rve

+1

@rve: Dlaczego nie zamieściłeś go jako odpowiedzi? To jest dobre. –

Odpowiedz

44

__cplusplus powinna być zdefiniowana jako 199711L w ampułko-C++ 11 kompilatorów, 201103L w tych Działalność na rzecz C++ 11. Czy jest to znacznie pomocne w praktyce, to kolejne pytanie: większość kompilatorów jest tylko w połowie drogi, więc nie powinno go definiować jako 201103L, nawet jeśli wspierają one funkcje, którymi jesteś zainteresowany. I nie jest to niespotykane, żeby kompilator kłamał: kompilator, który definiuje go jako 199711L i nie obsługuje na przykład export dla szablonów. Ale nie ma standardowej funkcji według testu funkcji.

Najprostszym rozwiązaniem jest po prostu nie używać żadnej konkretnej nowej funkcji, dopóki nie będziesz mieć pewności, że wszystkie kompilatory ją obsługują. W każdym razie musisz napisać i wesprzeć kod awaryjny; po co utrzymywać dwie wersje. Jedynym wyjątkiem od tej reguły mogą być nowe funkcje, które mają wpływ na wydajność: czy kompilator obsługuje semantykę ruchu, czy nie. W takich przypadkach proponuję plik zależny od kompilatora, który sam napiszesz na podstawie dokumentacji kompilatora i testów osobistych; tylko dlatego, że kompilator może udokumentować, że obsługuje określoną funkcję, nie oznacza, że ​​jego obsługa jest wolna od błędów. Po prostu utwórz katalog na docelowy kompilator, umieść tam ten plik i określ właściwą opcję -I lub /I w pliku makefile lub projekcie.

A twoje testy powinny być coś wzdłuż linii:

#ifdef HAS_MOVE_SEMANTICS 
... 
#endif 

zamiast tylko na wersji kompilatora, czy cokolwiek innego.

+0

"I nie jest to niesłychane, że kompilator kłamie" - a GCC zaskakująco mówi prawdę. Lub raczej niektóre wersje. Przed około 4,7-ish, '__cplusplus' to' 1', co jest poprawne, ponieważ nie jest kompletną implementacją C++ 98. Następnie została zmieniona na wymaganą zgodność w trybie C++ 98. –

+0

@SteveJessop g ++ nigdy nie posiadał pełnej implementacji C++ 98 lub C++ 03. Nigdy nie zaimplementował "eksportu". Więc jeśli '__cplusplus' to' 199711L', to kłamie. (Oczywiście, w tej sytuacji nie ma mowy o samotności.) –

+7

Tak właśnie mówię, GCC zostało ostatnio zmienione na kłamstwo, podczas gdy wcześniej mówiono prawdę. Powodem jest to, że nie można było stwierdzić, czy mówi prawdę o nie wdrażaniu C++ 98, czy mówiąc prawdę o nie implementowaniu C++ 11. Teraz możesz rozróżnić, kiedy chodzi o implementację C++ 98, i kiedy mówi prawdę o nie implementowaniu C++ 11. Yippee. Nie sądzę, by ktokolwiek kiedykolwiek zaimplementował C++ 98 (lub C++ 03), więc dokładna wartość '__cplusplus' jest w zasadzie bezużyteczna. Zawsze jest to specyficzne dla implementacji lub kłamstwa. –

25

Można sprawdzić wartość makra __cplusplus. W przypadku C++ 11 jest większy niż 199711L.

Więc coś

#if __cplusplus > 199711L 

#endif 
+3

z zastrzeżeniem, że nie ma jeszcze * pełnego * wsparcia. – juanchopanza

+1

@juanchopanza tak, to w żaden sposób nie gwarantuje pełnego wsparcia dla C++ 11, lub że kompilator w ogóle obsługuje C++ 11 (ale prawdopodobnie jest to najlepsze, co można uzyskać). –

+8

Również z zastrzeżeniem, że kompilatory są znane z kłamstwa. –

7

Biblioteka Boost.Config zapewnia można użyć do warunkowej kompilacji na podstawie obecności danej funkcji C++ 11.

(dla kompilatora, 11 wsparcie C++ nie musi być wszystko albo nic propozycją. Na przykład, rozważmy, jak Microsoft cherry picked which C++11 features umieścić w Visual Studio 2012 w oparciu o to, co ich zdaniem byłoby najbardziej korzystne swoich klientów).

Powiązane problemy