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.
shared_ptr is now part of the C++11 Standard, as std::shared_ptr . Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically allocated array. This is accomplished by using an array type ( T[] or T[N] ) as the template parameter.
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr . Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.
The smart pointer has an internal counter which is decreased each time that a std::shared_ptr , pointing to the same resource, goes out of scope – this technique is called reference counting. When the last shared pointer is destroyed, the counter goes to zero, and the memory is deallocated.
The Thread Safety section of the Boost shared_ptr documentation says "shared_ptr objects offer the same level of thread safety as built-in types." The implementation must ensure that concurrent updates to separate shared_ptr instances are correct even when those instances share a reference count e.g.
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.
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