Какова ценность __cplusplus для С++ 17?

Мы пытаемся проверить код под С++ 17 и его изменить на std::uncaught_exception. Я не могу заставить GCC предоставить значение __cplusplus:

$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$

и

$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.

Каково значение __cplusplus при использовании С++ 17?

Ответ 1

Каково значение __cplusplus при использовании С++ 17?

В соответствии с проектом стандарта N4594 §16.8/p1 Предопределенные имена макросов [cpp.predefined] (Emphasis Mine):

При этом будут определены следующие имена макросов: __cplusplus Имя __cplusplus определяется значением 201402L при компиляции единицы перевода С++. 156

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

Однако такое же значение назначается для стандарта С++ 14. По-видимому, кажется, что стандартного значения __cplusplus еще не установлено для стандарта С++ 17.

В версиях GCC 6.1 и 7.0 значение изменяется на 201500

Live Demo

В версии Clang 3.8 и 3.9 значение не изменяется 201406.

Следовательно, вам придется немного подождать, пока выйдет стандартное значение.

--- Обновить ---

В соответствии со стандартом С++ §19.8/p1 Предопределенные имена макросов [cpp.predefined] (Emphasis Mine):

1 Следующие имена макросов должны быть определены реализация:

__cplusplus Целый литерал 201703L.

Таким образом, значение __cplusplus при использовании С++ 17 должно быть 201703L.

Ответ 2

Я бы попробовал

#if __cplusplus > 201402L
  // C__17 code here
  ...
#endif

Другими словами, тестирование более чем на С++ 14 должно работать, поскольку компиляторы добавляют дополнительные функции. Как упоминалось выше, gcc использует 201500L. Похоже, что clang использует 201406L (через четыре месяца после С++ 14).

Использование вышеперечисленного должно быть кросс-платформенным и работать, даже когда С++ 17 выйдет с реальным значением для __cplusplus. Для получения дополнительной информации об эволюционных функциях попробуйте макросы тестирования функций.

Ответ 3

Я понимаю, что вы задавали этот вопрос, ссылаясь на компилятор Gnu C++, который вы используете, но вы, возможно, захотите узнать, что происходит с компилятором Visual C++, и, строго говоря, ваш вопрос не задавался о конкретном компиляторе.

В настоящее время, на дату этой публикации, компилятор V C++ 2017 устанавливает __cplusplus на 199711L, а не то, что вы могли бы ожидать, если вы установите компилятор на использование C++ 17.

Чтобы он правильно отображал отчет, вы также должны установить /Zc:__cplusplus.

(источник: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017)

А почему? Ну... по их словам:

Мы попытались обновить макрос по умолчанию и обнаружили, что код не компилируется правильно, когда мы меняем значение __cplusplus.

(источник: https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/)

Ответ 4

Я действительно не знаю, почему __cplusplus не отображается как обычный макрос, но я предполагаю, что вы не можете переопределить его. Вот как я определяю его значение.

#include <iostream>
int main( int argc, char** argv )
{
  std::cout << __cplusplus << std::endl;
  return 0;
}

Затем компиляция показывает значение.

$ g++-6 test.cpp && ./a.out
201402
$ g++-6 -std=c++17 test.cpp && ./a.out
201500

Я бы проверил, не является ли это >= 201500, а не проверяет любое конкретное значение.

Ответ 5

Обычно вы должны использовать __cplusplus define для обнаружения 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