Jak określić wersję standardu C ++ używanego przez kompilator?

115

Jak określić, która wersja standardu C ++ została zaimplementowana przez Twój kompilator? O ile wiem, poniżej znane mi standardy:

  • C ++ 03
  • C ++ 98
jasonline
źródło
3
Oznaczyłeś to c ++ , ale dwa z trzech wymienionych standardów nie są standardami C ++. Które języki Cię interesują?
Rob Kennedy,
1
A pytanie zostało zadane zaledwie kilka minut temu. ( stackoverflow.com/questions/7132440/… )
Mat.
1
@Mat: Pozowany i zamknięty, ponieważ pytanie było bzdurne i zawierało inne arbitralne bzdury. Opublikowałem to ponownie w przyzwoitej formie. Z przyjemnością zamknę to, jeśli wygląda na to, że oryginał zostanie naprawiony i ożywiony, ale nie wstrzymuję oddechu.
Wyścigi lekkości na orbicie,
1
@Mat: Cóż, najlepszą odpowiedzią nie jest statyczna lista kompilatorów, ale sposób samodzielnego określenia, co jest używane. Więc proszę.
Wyścigi lekkości na orbicie
1
@Als: To będzie wkrótce. Obiecuję. Poza tym c++-faqznacznik nie ma żadnego rzeczywistego warunku wstępnego „ile razy pytano”, które musisz zdać; chodzi bardziej o format i ogólność rzeczy.
Wyścigi lekkości na orbicie

Odpowiedzi:

13

Według mojej wiedzy nie ma ogólnego sposobu, aby to zrobić. Jeśli spojrzysz na nagłówki wieloplatformowych / wielu kompilatorów obsługujących biblioteki, zawsze znajdziesz wiele definicji, które używają konstrukcji specyficznych dla kompilatora do określenia takich rzeczy:

/*Define Microsoft Visual C++ .NET (32-bit) compiler */
#if (defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER >= 1300)
     ...
#endif

/*Define Borland 5.0 C++ (16-bit) compiler */
#if defined(__BORLANDC__) && !defined(__WIN32__)
     ...
#endif

Prawdopodobnie będziesz musiał sam dokonać takich definicji dla wszystkich kompilatorów, których używasz.

RED SOFT ADAIR
źródło
1
Nie jest to jednak moja oczekiwana odpowiedź, ale wydaje mi się, że nie ma uniwersalnego sposobu, aby się tego dowiedzieć.
jasonline
248

Z FAQ Bjarne Stroustrup C ++ 0x :

__cplusplus

W C ++ 0x makro __cpluspluszostanie ustawione na wartość, która różni się (jest większa) od wartości bieżącej 199711L.

Chociaż nie jest to tak pomocne, jak by się chciało. gcc(najwyraźniej przez prawie 10 lat) miał tę wartość ustawioną na 1, wykluczając jeden główny kompilator, dopóki nie została naprawiona, gdy wyszło gcc 4.7.0 .

Oto standardy C ++ i jakiej wartości powinieneś się spodziewać __cplusplus:

  • C ++ przed C ++ 98: __cplusplusjest 1.
  • C ++ 98: __cplusplusjest 199711L.
  • C ++ 98 + TR1: Czyta się to jako C ++ 98 i nie ma sposobu, aby sprawdzić, czy wiem.
  • C ++ 11: __cplusplusjest 201103L.
  • C ++ 14: __cplusplusjest 201402L.
  • C ++ 17: __cplusplusjest 201703L.

Jeśli kompilator może być starszy gcc, musimy uciec się do hakera specyficznego dla kompilatora (spójrz na makro wersji, porównaj je z tabelą z zaimplementowanymi funkcjami) lub użyj Boost.Config (który zapewnia odpowiednie makra ). Zaletą tego jest to, że możemy faktycznie wybrać określone funkcje nowego standardu i napisać obejście, jeśli brakuje tej funkcji. Jest to często preferowane w stosunku do rozwiązania hurtowego, ponieważ niektóre kompilatory twierdzą, że implementują C ++ 11, ale oferują tylko podzbiór funkcji.

Wiki Stdcxx zawiera obszerną macierz do obsługi kompilatorów funkcji C ++ 0x (jeśli odważysz się sprawdzić te funkcje samodzielnie).

Niestety, dokładniejsze sprawdzanie funkcji (np. Poszczególnych funkcji bibliotecznych, takich jak std::copy_if) może być wykonane tylko w systemie kompilacji Twojej aplikacji (uruchom kod z funkcją, sprawdź, czy skompilował i dało poprawne wyniki - autoconfjest narzędziem z wyboru, jeśli bierzesz ta trasa).

pmr
źródło
Czy nie wygląda na to, że dostawcy kompilatorów to aktualizują - może czekają, aż w pełni dostosują się do standardu? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden
2
@prnr: To może być prawda, ale to użytkownik, który zadał pytanie, decyduje, którą odpowiedź zaakceptować. W momencie wysłania odpowiedzi, która jest aktualnie oznaczona jako zaakceptowana, była poprawna, więc oryginalny plakat ją zaakceptował. Ten użytkownik może zdecydować o zmianie zaakceptowanej odpowiedzi, ale może nie być już aktywny w serwisie. Zobacz: meta.stackexchange.com/questions/120568/…
Dan Korn
3
vs2017 podaje wartość __cplusplus 199711
Al Mamun
5
@AlMamun Microsoft częściowo naprawiono __cplusplustylko w VS 15.7. Zobacz ich blog zespołu Visual C ++
Ivan_Bereziuk,
1
Link do FAQ jest uszkodzony.
brainplot
38

Proszę uruchomić poniższy kod, aby sprawdzić wersję.

#include<iostream>

int main() {
    if (__cplusplus == 201703L) std::cout << "C++17\n";
    else if (__cplusplus == 201402L) std::cout << "C++14\n";
    else if (__cplusplus == 201103L) std::cout << "C++11\n";
    else if (__cplusplus == 199711L) std::cout << "C++98\n";
    else std::cout << "pre-standard C++\n";
}
Deepanshu
źródło
8
To zabawne, ponieważ w studiach wizualnych wartość __cplusplus to 199711L, a kod, który przesłałeś, zwrócił c ++ 98, jednak użyłem funkcji z c ++ 14, w tym szablonów zmiennych i decltype (auto). Czy jest możliwe, że została zaimplementowana niewłaściwa wersja makra?
Colin Hicks
2
Zobacz: devblogs.microsoft.com/cppblog/… (TLDR: określ flagę /Zc:__cplusplus)
Daan Timmer
@DaanTimmer Jestem zdezorientowany tym artykułem, wydaje się, że zakładam wiedzę o tym, jak używać /Zc:__cplusplusflagi. Nie mogę po prostu std::cout << /Zc:__cplusplus;dlatego, że dwukropki i ukośniki nie mogą być oczywiście częścią nazw zmiennych. Czy jesteś w stanie wyjaśnić, jak to zrobić? Dzięki.
A__
7

W zależności od tego, co chcesz osiągnąć, Boost.Config może Ci pomóc. Nie zapewnia wykrywania wersji standardowej, ale udostępnia makra, które pozwalają sprawdzić obsługę określonego języka / funkcji kompilatora.

Björn Pollex
źródło
3
W każdym razie sprawdzanie funkcji jest prawdopodobnie lepszym pomysłem niż sprawdzanie standardowych wersji. Niewiele kompilatorów obsługuje wszystko począwszy od standardu, ale jeśli wszystkie obsługują ograniczoną liczbę potrzebnych funkcji, nie ma znaczenia, czy pozostałe funkcje z danego standardu są zaimplementowane i działają poprawnie.
Rob Kennedy,
4

__cplusplus

W C ++ 0x makro __cplusplus zostanie ustawione na wartość, która różni się od bieżącego 199711L (jest większa niż).

C ++ 0x FAQ autorstwa BS

Vinzenz
źródło
0

Po szybkim wygooglowaniu :

__STDC__i __STDC_VERSION__zobacz tutaj

Tor Valamo
źródło
To, czy __STDC__jest zdefiniowane i jaka jest jego wartość, są zdefiniowane w implementacji w C ++.
Rob Kennedy,
@Rob: Tak, jest. @Tor: Próbowałem w VC ++ 2005, ale jest napisane, że STDC to niezadeklarowany identyfikator. Jest jednak wymieniony jako jedno z tych wstępnie zdefiniowanych makr. Jednak STDC_VERSION nie istnieje.
jasonline
Informuje o wersji języka programowania C obsługiwanej przez kompilator. Nie mówi nic o obsługiwanej wersji języka C ++.
Dan Molding
0

Zwykle __cplusplusdo wykrywania c ++ 17 należy używać funkcji define, ale domyślnie kompilator firmy Microsoft nie definiuje poprawnie tego makra, patrz https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - potrzebujesz aby zmodyfikować ustawienia projektu, aby uwzględnić /Zc:__cplusplusprzełącznik, lub możesz użyć takiej składni:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
TarmoPikaro
źródło