【问题标题】:How do I reliably detect support for nullptr?如何可靠地检测对 nullptr 的支持?
【发布时间】:2017-07-13 02:08:26
【问题描述】:

我需要将 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 实际可用时,它不会打印出错误。所以根本没有。

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

【问题讨论】:

  • 如果它不可用,使用它的代码将无法编译。对我来说,这似乎是一个非常简单的指标。为什么你认为你需要(或可以)“向后移植”它?
  • 查看 Boost.Config 的 BOOST_NO_CXX11_NULLPTR 宏。要么使用 Boost.Config,要么复制他们用来确定这一点的等效逻辑。
  • @Matt 您是否尝试过对 nullptr_t 进行类型特征检查? sth like std::is_same or sth like that.
  • 典型的 XY 问题。只需使用NULL,直到您不必支持旧版编译器。
  • @matt 最后的编辑应该是一个答案。

标签: c++ c++11


【解决方案1】:
  • 如果您使用的是 Boost,Boost.Config 会提供 BOOST_NO_CXX11_NULLPTR 宏。

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

  • 如果您使用 CMake,则可以使用 compiler feature detection(特别是 cxx_nullptr)有条件地定义宏。

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

【讨论】:

  • 关于#if !defined(nullptr),我也是这么想的,但是很多人都在发布一个问题的答案,这些问题已经实施了检查,以加强它的正确性。所以我开始怀疑我所假设的是真的。这是为了证实我的第一个想法。
  • @Matt 您是否尝试过对 nullptr_t 进行类型特征检查? sth like std::is_same or sth like that.
  • 安装库时不 Boost 构建此配置吗?因此,除非您有完整的受支持编译器列表或一些外部构建工具来测试语言功能,否则在分发仅标头库时不能使用此解决方案?
  • 所以我们没有使用 boost,我不能在这个东西中包含 boost 头文件,所以我最终做的是拉出 boost 库并提取所需的部分。
【解决方案2】:

感谢 boost 库的提示,这就是我最终得到的。我敢肯定,我不是唯一一个想要这个的人。

#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

【讨论】:

    猜你喜欢
    • 2011-05-06
    • 2011-06-21
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多