Как определить версию стандарта C ++, используемую компилятором?

116

Как вы определяете, какая версия стандарта C ++ реализована вашим компилятором? Насколько мне известно, ниже приведены известные мне стандарты:

  • C ++ 03
  • С ++ 98
Джейсонлайн
источник
3
Вы отметили этот C ++ , но два из трех перечисленных вами стандартов не являются стандартами C ++. Какой язык (языки) вас интересует?
Роб Кеннеди,
1
И вопрос задан буквально пару минут назад. ( stackoverflow.com/questions/7132440/… )
Мат
1
@Mat: поставлен и закрыт, потому что вопрос был вздором и содержал какую-то другую произвольную чепуху. Перепостил в достойном виде. Я был бы счастлив закрыть это, если кажется, что оригинал будет исправлен и возрожден, но я не задерживаю дыхание.
Гонки за легкостью на орбите,
1
@Mat: Что ж, лучший ответ - это не статический список компиляторов, а средство определения для себя, что используется. Итак, поехали.
Гонки легкости на орбите
1
@Als: Скоро будет. Обещаю. Кроме того, у c++-faqтега нет какого-либо фактического необходимого «количества запросов», которое вы должны передать; это больше о формате и общности вещи.
Гонки легкости на орбите,

Ответы:

13

Насколько мне известно, универсального способа сделать это не существует. Если вы посмотрите на заголовки межплатформенных / нескольких поддерживающих компиляторов библиотек, вы всегда найдете множество определений, которые используют специфические конструкции компилятора для определения таких вещей:

/*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

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

КРАСНЫЙ МЯГКИЙ ADAIR
источник
1
Это не то, чего я ожидал, но я полагаю, что универсального способа узнать его просто не существует.
jasonline
248

Из FAQ Бьярна Страуструпа C ++ 0x :

__cplusplus

В C ++ 0x макросу __cplusplusбудет присвоено значение, которое отличается от текущего (больше) 199711L.

Хотя это не так полезно, как хотелось бы. gcc(по всей видимости, почти 10 лет) это значение было установлено равным 1, исключая один из основных компиляторов, пока оно не было исправлено, когда вышел gcc 4.7.0 .

Это стандарты C ++ и то, что вы можете ожидать от них __cplusplus:

  • C ++ до C ++ 98: __cplusplusесть 1.
  • C ++ 98: __cplusplusесть 199711L.
  • C ++ 98 + TR1: читается как C ++ 98, и я не знаю, как это проверить.
  • C ++ 11: __cplusplusесть 201103L.
  • C ++ 14: __cplusplusесть 201402L.
  • C ++ 17: __cplusplusесть 201703L.

Если компилятор может быть более gccранним, нам нужно прибегнуть к конкретным хакерским действиям компилятора (посмотрите на макрос версии, сравните его с таблицей с реализованными функциями) или используйте Boost.Config (который предоставляет соответствующие макросы ). Преимущество этого состоит в том, что мы действительно можем выбрать конкретные функции нового стандарта и написать обходной путь, если эта функция отсутствует. Это часто предпочтительнее оптового решения, поскольку некоторые компиляторы утверждают, что реализуют C ++ 11, но предлагают только подмножество функций.

Stdcxx Wiki содержит исчерпывающую матрицу для поддержки компилятором функций C ++ 0x (если вы осмеливаетесь проверить эти функции самостоятельно).

К сожалению, более детальная проверка функций (например, отдельных библиотечных функций std::copy_if) может быть выполнена только в системе сборки вашего приложения (запустите код с функцией, проверьте, скомпилирован ли он и дает ли правильные результаты - autoconfэто инструмент выбора, если вы выбираете этот маршрут).

PMR
источник
Не похоже, что поставщики компиляторов обновляют это - может быть, они ждут, пока они полностью не будут соответствовать стандарту? ( Stackoverflow.com/q/14131454/11698 )
Ричард Корден,
2
@prnr: Возможно, это правда, но пользователь, задавший вопрос, должен решить, какой ответ принять. На тот момент, когда был опубликован ответ, который в настоящее время отмечен как принятый, он был правильным, поэтому исходный постер принял его. Этот пользователь может решить изменить принятый ответ, но он больше не будет активен на сайте. См .: meta.stackexchange.com/questions/120568/…
Дэн Корн,
3
vs2017 дает значение __cplusplus 199711
Аль Мамун
5
@AlMamun Microsoft частично исправила __cplusplusтолько в VS 15.7. См. Их блог команды разработчиков Visual C ++
Ivan_Bereziuk
1
Ссылка на FAQ не работает.
Brainplot
39

Пожалуйста, запустите следующий код, чтобы проверить версию.

#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
источник
8
Это забавно, потому что в визуальных студиях значение __cplusplus - 199711L, а опубликованный вами код вернул C ++ 98, однако я использовал функции из C ++ 14, включая шаблоны переменных и decltype (auto). Возможно, была реализована неправильная версия макроса?
Колин Хикс
2
См .: devblogs.microsoft.com/cppblog/… ( TL ; DR : укажите флаг /Zc:__cplusplus)
Даан Тиммер,
@DaanTimmer Меня смущает эта статья, кажется, предполагается, что я знаю, как использовать /Zc:__cplusplusфлаг. Я не могу просто std::cout << /Zc:__cplusplus;потому, что двоеточия и косые черты, конечно же, не могут быть частью имен переменных. Вы можете объяснить, как это сделать? Спасибо.
A__
7

В зависимости от того, чего вы хотите достичь, Boost.Config может вам помочь. Он не обеспечивает обнаружение стандартной версии, но предоставляет макросы, которые позволяют вам проверять поддержку определенного языка / функций компилятора.

Бьорн Поллекс
источник
3
В любом случае проверка функций, вероятно, лучше, чем проверка стандартных версий. Немногие компиляторы поддерживают все, начиная со стандарта, но если все они поддерживают ограниченное количество необходимых вам функций, то на самом деле не имеет значения, реализованы ли и правильно ли работают остальные функции из данного стандарта.
Роб Кеннеди,
4

__cplusplus

В C ++ 0x макросу __cplusplus будет присвоено значение, которое отличается (больше) от текущего 199711L.

C ++ 0x FAQ от BS

Vinzenz
источник
0

После быстрого поиска в Google :

__STDC__и __STDC_VERSION__смотрите здесь

Тор Валамо
источник
__STDC__Определение того, определено ли и каково его значение, определяется реализацией в C ++.
Роб Кеннеди,
@ Роб: Да, это так. @Tor: Я пробовал использовать VC ++ 2005, но там сказано, что STDC - необъявленный идентификатор. Однако он указан как один из тех предопределенных макросов. Однако STDC_VERSION не существует.
jasonline
Это сообщает вам версию языка программирования C, поддерживаемую компилятором. Он ничего не говорит вам о поддерживаемой версии языка C ++.
Дэн Молдинг
0

Обычно вы должны использовать __cplusplusопределение для обнаружения c ++ 17, но по умолчанию компилятор Microsoft не определяет этот макрос должным образом, см. Https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - вам нужно чтобы либо изменить настройки проекта, чтобы включить /Zc:__cplusplusпереключатель, либо вы можете использовать такой синтаксис:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
ТармоПикаро
источник