I think this is part of the problem at No type named 'unique_ptr' in namespace 'std' when compiling under LLVM/Clang. According to Marshall Clow, I can detect -stdlib=libc++
via _LIBCPP_VERSION
:
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
Unfortunately, that breaks down with Apple's Clang (3.4-SVN) and the Clang (3.6) I built from sources after downloading from the LLVM project. I'm guessing the test is only valid under Xcode.
How can I reliably detect -stdlib=libc++
in the preprocessor?
Here is the test case:
$ 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;
}
This project does not use Autotools, Cmake, Boost, or other external libraries or frameworks.
The only effect -stdlib=libc++
has on the preprocessor is to change the include paths it uses to find standard library headers, so you can't detect the presence of -stdlib=libc++
on the command-line per se, you can only detect which standard library headers get included. Obviously you can't detect that without actually including one or more standard library headers.
If you include any libc++ header then _LIBCPP_VERSION
will be defined, so the way to detect -stdlib=libc++
is to include at least one C++ library header and check for _LIBCPP_VERSION
.
For libc++ it is recommended to #include <ciso646>
which serves no purpose in C++ and declares nothing, but for libc++ does define the _LIBCPP_VERSION
macro. However, for libstdc++ historically <ciso646>
did not define any macros such as __GLIBCXX__
that can be used to detect libstdc++. That changed with GCC 6.1 so <ciso646>
can be used now, but for older releases you need to include a different header to detect libstdc++.
来源:https://stackoverflow.com/questions/31657499/how-to-detect-stdlib-libc-in-the-preprocessor