2017-02-22 4 views
8

Мне нужно backport nullptr в библиотеку кросс-платформы, которую мы имеем, но у меня возникли проблемы с надежной проверкой поддержки nullptr.Как я могу надежно обнаружить поддержку nullptr?

Изначально у меня было так:

#if __cplusplus >= 201103L || (__cplusplus < 200000 && __cplusplus >= 199711L) 
    // nullptr should be ok 
#else 
    // Too old 
#endif 

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

Одно из опубликованных сообщений в блоге 199711L было значением, которое MS-компиляторы используют для указания частичной поддержки C++ 11. Но я замечаю, что g ++ 5.4 производит это значение по умолчанию. Пока вы прямо не скажете ему использовать компиляцию с -std = C++ 11. Но тогда, если вы скажете, что это стандарт C++ 98, значение 199711 все еще отображается. Это звучит неправильно для меня. Так что это не хорошая проверка!

Затем я увидел someone doing this с ответом, в котором утверждалось, что он может работать. Ну, это не так.

#if !defined(nullptr) 
#endif 

Но я не уверен, что вы можете это сделать. Поэтому я протестировал это следующим образом:

#if defined(nullptr) 
#error "null ptr defined" 
#endif 

Угадайте, что? который не печатает ошибку, когда nullptr фактически доступен. Так что это совсем не так.

Как определить версию nullptr или компилятора под linux/windows и OSX (clang)/android.

+1

Если он недоступен, код, который его использует, не будет компилироваться. Это кажется мне довольно простым показателем. И почему, по-вашему, вам нужно (или может) «вернуть» его? –

+0

Посмотрите на макрос Boost.Config 'BOOST_NO_CXX11_NULLPTR'. Либо используйте Boost.Config, либо дублируйте эквивалентную логику, которую они используют, чтобы определить это. – GManNickG

+0

@ Можете ли вы попробовать проверку typetrait на nullptr_t? sth, как std :: is_same или sth, как это. –

ответ

8
  • Если вы используете Boost, Boost.Config обеспечивает BOOST_NO_CXX11_NULLPTR макрос.

    Boost реализует это, определяя его для каждой компиляции-версии-комбо, которая не поддерживает его, поэтому вы не можете легко дублировать функциональность.

  • Если вы используете CMake, вы можете использовать compiler feature detection (в частности, cxx_nullptr) для условного определения макроса.

#if !defined(nullptr) не работает, потому что nullptr не макро.

+0

относительно #if! Defined (nullptr), это то, о чем я думал, но так много людей отправляли ответы на вопрос, который внедрил проверку таким образом, чтобы это было правильно. Поэтому я начал сомневаться в том, что я предполагал, что это правда. Это для того, чтобы подтвердить мою первую мысль. – Matt

+0

@ Можете ли вы попробовать проверку typetrait для nullptr_t? sth, как std :: is_same или sth, как это. –

+0

Не Boost создавать эту конфигурацию при установке библиотеки? Итак, если у вас нет полного списка поддерживаемых компиляторов или какого-либо внешнего инструмента сборки для проверки языковых функций, это решение не может использоваться при распространении библиотеки только заголовка? – Mikhail

2

Благодаря подсказкам для библиотеки ускорения это то, с чем я столкнулся. Я уверен, что я не единственный, кто этого хочет.

#if defined(__GNUC__) 
# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) 
# define GCC_CXX11 
# endif 
# if (GCC_VERSION < 40600) || !defined(GCC_CXX11) 
# define NO_CXX11_NULLPTR 
# endif 
#endif 

#if defined(_MSC_VER) 
# if (_MSC_VER < 1600) 
# define NO_CXX11_NULLPTR 
# endif 
#endif 

#if defined(__clang__) 
# if !__has_feature(cxx_nullptr) 
# define NO_CXX11_NULLPTR 
# endif 
#endif 

#if defined(NO_CXX11_NULLPTR) 
# pragma message("Defining nullptr") 
# define nullptr 0 
#endif 
Смежные вопросы