Reputation: 4356
We all know that both boost and c++11 has support for shared_ptr. Some compiler has support for c++11 while some doesn't. I would like to write my code so that when compiler support c++11 shared_ptr, it uses std::shared_ptr; when it doesn't, use boost::shared_ptr. What is the common/best practice for that?
Let me confine the discussion to GCC but not to particular version.
Upvotes: 7
Views: 1323
Reputation: 54787
You can just pull them into a custom namespace
#ifdef HAS_STD_SHARED_PTR
#include <memory>
#define SHARED_PTR_NAMESPACE std
#else
#include <boost/shared_ptr.hpp>
#define SHARED_PTR_NAMESPACE boost
#endif
namespace my_namespace {
using SHARED_PTR_NAMESPACE::shared_ptr;
using SHARED_PTR_NAMESPACE::make_shared;
}
#undef SHARED_PTR_NAMESPACE
The HAS_STD_SHARED_PTR
flag needs to be set by the build environment. CMake provides several mechanisms for detecting such features and newer C++ implementations also provide feature test macros for quick and easy detection of newer features.
Upvotes: 3
Reputation: 15089
The only way I am aware to detect whether GCC is using C++0x/C++11, as of today, is to check for the predefined macro __GXX_EXPERIMENTAL_CXX0X__
:
#ifdef __GXX_EXPERIMENTAL_CXX0X__
// C++11 code
#else
// C++03 code
#endif
Note that this may change in the future (hence the EXPERIMENTAL
part of the macro).
Edit: in fact there's a better way I didn't know of until @stephan pointed it out in a comment:
16.8/1 [cpp.predefined]
The following macro names shall be defined by the implementation:
__cplusplus
The name
__cplusplus
is defined to the value201103L
when compiling a C ++ translation unit.157157) It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming compilers should use a value with at most five decimal digits.
So I guess you could do:
#if defined(__cplusplus) && (__cplusplus >= 201103L)
But I fear this wouldn't work with pre-standard C++0x GCC versions. So I'd probably use both __GXX_EXPERIMENTAL_CXX0X__
and __cplusplus
together:
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L))
However this may not always be enough to just detect whether C++0x/C++11 support is enabled: C++11 support has changed a lot throughout GCC versions, not only at the core language level but at the library level too.
My best bet would be to find which minimal GCC version you find acceptable for C++11 support and combine the above tests with a GCC version test, eg:
#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ >= 5)) // for GCC 4.7+
boost
and std
Now, to switch between boost::shared_ptr
and std::shared_ptr
it's a bit cumbersome because C++03 doesn't support templated typedefs. I for one would wrap the required definitions in a template struct
:
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L))) \
&& (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ >= 5))
template<typename T>
struct my_shared_ptr {
typedef std::shared_ptr<T> type;
// you may also want to forward make_shared etc, this is left as an exercise
};
#else
template<typename T>
struct my_shared_ptr {
typedef boost::shared_ptr<T> type;
// you may also want to forward make_shared etc, this is left as an exercise
};
#endif
my_shared_ptr<int>::type ptr(new int);
Edit: (again) whoops I just noticed @ComicSansMS's way of importing the right shared_ptr
with a simple non-template using
directive. Dunno why I didn't think about that.
Still, I stand with the way I described of detecting C++0x/C++11 on GCC.
Upvotes: 4