如何检测预处理器中的 -stdlib=libc++?

How to detect -stdlib=libc++ in the preprocessor?

我认为这是 . According to Marshall Clow 的部分问题,我可以通过 _LIBCPP_VERSION:

检测到 -stdlib=libc++

If you're writing cross-platform code, sometimes you need to know what standard library you are using. In theory, they should all offer equivalent functionality, but that's just theory. Sometimes you just need to know. The best way to check for libc++ is to look for the preprocessor symbol _LIBCPP_VERSION. If that's defined, then you're using libc++.

#ifdef  _LIBCPP_VERSION
//  libc++ specific code here
#else
//  generic code here
#endif

不幸的是,Apple 的 Clang (3.4-SVN) 和我从 LLVM 项目下载后从源构建的 Clang (3.6) 出现故障。我猜测试仅在 Xcode.

下有效

如何在预处理器中可靠地检测 -stdlib=libc++


这里是测试用例:

$ cat test-clapple.cxx

// Need to test {C++03,C++11} x {libc++, no libc++}

// c++ -c test-clapple.cxx
//     - OK
// c++ -stdlib=libc++ -c test-clapple.cxx
//     - OK
// c++ -std=c++11 -c test-clapple.cxx
//     - FAILS, no type named 'unique_ptr' in namespace 'std'
// c++ -std=c++11 -stdlib=libc++ -c test-clapple.cxx
//     - OK

#include <ciso646>

#if (__cplusplus >= 201103L) || (_MSC_VER >= 1600)
# pragma message "C++11"
#elif (__cplusplus >= 199711L)
# pragma message "C++03"
#endif

#if (_LIBCPP_VERSION)
# pragma message "libc++"
#else
# pragma message "no libc++"
#endif

#if defined(__apple_build_version__)
# pragma message "Apple build"
#else
# pragma message "non-Apple build"
#endif

#if (__cplusplus >= 201103L) || (_MSC_VER >= 1600) // C++11
# include <memory>
#else
# include <tr1/memory>
#endif

// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1600)
  template<typename T>
    using auto_ptr = std::unique_ptr<T>;
#else
  using std::auto_ptr;
#endif // C++11

int main(int argc, char* argv[])
{
    return argc;
}

此项目不使用 Autotools、Cmake、Boost 或其他外部库或框架。

-stdlib=libc++ 对预处理器的唯一影响是更改它用于查找标准库 header 的包含路径,因此您无法检测到 -stdlib=libc++ 的存在在 command-line 本身,您只能检测包含哪个标准库 header。显然,如果不实际包含一个或多个标准库 headers.

,您将无法检测到这一点

如果你包含任何libc++ header那么_LIBCPP_VERSION将被定义,所以检测-stdlib=libc++的方法是包含至少一个C++库header并检查_LIBCPP_VERSION.

在C++20及以后的版本中,推荐#include <version>,这是专门为此创建的。在 C++20 之前,建议使用 #include <ciso646>,它在 C++ 中没有任何作用且不声明任何内容,但对于 libc++ 确实定义了 _LIBCPP_VERSION 宏。但是,对于 libstdc++,历史上 <ciso646> 确实 没有 定义任何可用于检测 libstdc++ 的宏,例如 __GLIBCXX__。 GCC 6.1 改变了这一点,所以现在可以使用 <ciso646>,但对于旧版本,您需要包含一个不同的 header 来检测 libstdc++。