如何可靠地检测对nullptr的支持?

时间:2017-02-22 20:17:54

标签: c++ c++11

我需要将nullptr backport到我们拥有的跨平台库,但是我无法对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实际可用时,它不会打印出错误。所以根本就没有。

如何在linux / windows和OSX(clang)/ android下检测nullptr或编译器版本。

2 个答案:

答案 0 :(得分:8)

  • 如果您使用的是Boost,Boost.Config会提供BOOST_NO_CXX11_NULLPTR宏。

    Boost通过为每个不支持它的编译器版本组合定义它来实现这一点,因此您无法轻易复制该功能。

  • 如果您使用的是CMake,则可以使用compiler feature detection(具体为cxx_nullptr)来有条件地定义宏。

#if !defined(nullptr)不起作用,因为nullptr不是宏。

答案 1 :(得分:3)

感谢提升库的提示,这就是我最终的结果。我确定我不是唯一一个想要这个的人。

#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