I've got an Xcode project that I'm migrating to use with clang's option -stdlib libc++
, to enable C++11 support. Some of my source files need to know which library is being used, for instance so that I do things like this:
#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
I'm having trouble though finding the preprocessor macros (if indeed there are any) that are set for this option. I've tried dumping the outputs of clang with:
clang -x c++ -std=c++11 -stdlib=libc++ -dM -E - < /dev/null
to compare with:
clang -x c++ -std=c++11 -stdlib=libstdc++ -dM -E - < /dev/null
but this gives the same results. Note that I don't want to switch on whether we're using the c++11 language setting, but whether we're using the c++11 library. Is there any reliable way of detecting this in the code?
I don't know of any sure way that is guaranteed to be portable, but this is what I use for now:
// 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
It's not great, but works for me for now.
libc++ defines _LIBCPP_VERSION
and stdc++ defines __GLIBCXX__
which is nice, but unfortunately these macros are not defined by the compiler. Instead, they're defined in a non-standard header file, and you cannot test their definition unless that header has been included.
Note: Apparently stdc++ defined __GLIBCPP__
in older versions instead. Since you require c++11, this isn't going to be a problem.
Clang (Edit: Standard since C++17) has a nice feature __has_include
which can be used to test for these but if neither header is found, the macro falls back to just including a standard header which hopefully uses the internal header under the hood. I have <ios>
here, but the choice of standard header to include is up to you. You can look for headers that include the internal header with something like (this is for gcc on linux):
grep -Rl '#include <bits/c++config.h>' /usr/include/c++
Pick any header that you're likely to use in the project anyway.
Since this isn't guaranteed to work for any given past or future compiler/standard library version, I wouldn't rely on these defines for anything but optional features like:
#ifdef __GLIBCXX__
std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With