检测clang是否正在使用c ++ 11或旧版libstdc ++标准库进行编译

时间:2014-03-20 11:15:55

标签: xcode c++11 clang

我有一个Xcode项目,我正在迁移以与clang的选项-stdlib libc++一起使用,以启用C ++ 11支持。我的一些源文件需要知道正在使用哪个库,例如我这样做:

#ifdef HAVE_CPP11_LIB_SUPPORT
  #include <memory>
#else 
  #include <tr1/memory>
#endif

#ifdef HAVE_CPP11_LIB_SUPPORT
  vector.emplace_back(newValue);
#else 
  vector.push_back(newValue);
#endif

虽然找到为此选项设置的预处理器宏(如果确实存在),但我遇到了麻烦。我试过将clang的输出转储为:

clang -x c++ -std=c++11 -stdlib=libc++ -dM -E - < /dev/null

与之比较:

clang -x c++ -std=c++11 -stdlib=libstdc++ -dM -E - < /dev/null

但是这给出了相同的结果。请注意,我不想打开我们是否使用c ++ 11 语言设置,但我们是否使用c ++ 11 。在代码中有没有可靠的方法来检测这个?

4 个答案:

答案 0 :(得分:7)

我不知道有任何可靠保证便携的方法,但这就是我现在使用的方法:

// libc++ detected:     _LIBCPP_VERSION
// libstdc++ detected:  __GLIBCXX__
#if defined(__clang__)
#   if __has_include(<__config>) // defines _LIBCPP_VERSION
#       include <__config>
#   elif __has_include(<bits/c++config.h>) // defines __GLIBCXX__
#       include <bits/c++config.h>
#   else
#       include <ios>
#   endif
#elif defined(__GNUC__) // gcc does not have __has_include
#   include <ios> // ios should include the c++config.h which defines __GLIBCXX__
#endif

这不好,但现在对我有用。

libc ++定义_LIBCPP_VERSION并且stdc ++定义__GLIBCXX__这很好,但不幸的是这些宏没有被编译器定义。相反,它们是在非标准头文件中定义的,除非包含该标题,否则无法测试它们的定义。

注意:显然stdc ++在旧版本中定义了__GLIBCPP__。由于你需要c ++ 11,这不会成为一个问题。

Clang (编辑:标准,因为C ++ 17)有一个很好的功能__has_include,可以用来测试这些,但如果没有找到任何标题,宏将回退到只包括一个标准的标题,希望在引擎盖下使用内部标题。我在这里<ios>,但要包含的标准标题的选择取决于您。您可以查找包含内部标题的标题(类似于Linux上的gcc):

grep -Rl '#include <bits/c++config.h>' /usr/include/c++

选择您可能在项目中使用的任何标题。

由于这不能保证适用于任何给定的过去或未来的编译器/标准库版本,我不会依赖这些定义,除了可选功能,如:

#ifdef __GLIBCXX__
    std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
#endif

答案 1 :(得分:1)

#ifdef __has_include
# if __has_include(<ciso646>)
#  include <ciso646>
#  if defined(_LIBCPP_VERSION)
#   define USING_LIBCPP 1
#  endif
# endif
#endif

#if !USING_LIBCPP
# define USING_LIBSTDCXX 1
#endif

答案 2 :(得分:0)

如果您正在编写这些类型的检查,我建议您选择编译器/库版本并要求更新或更新版本。半使用C ++ 11库功能是没有意义的。在Mac OS X上,只需要使用clang++ -stdlib=libc++编译。

答案 3 :(得分:0)

我使用下一个代码:

#include <cstddef> // for __GLIBCXX__

#ifdef __GLIBCXX__
#  include <tr1/memory>
#else
#  include <memory>
#endif

source