Boost :: shared_ptr and std :: shared_ptr coexistence

We all know that boost and C ++ 11 support shared_ptr. Some compilers have support for C ++ 11, and some do not. I would like to write my code so that with the support of the C ++ 11 shared_ptr compiler, it uses std :: shared_ptr; if not, use boost :: shared_ptr. What is the general / best practice for this?

Let me limit myself to a discussion of GCC, but not a specific version.

+7
source share
2 answers

You can simply paste 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 must be set by the build environment. CMake allows you to use common methods for detecting such functions .

+3
source

C ++ 0x / C ++ 11 Availability

The only way to find out if GCC uses C ++ 0x / C ++ 11 today is to check 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: there really is a better way I didn't know about until @stephan pointed this out in a comment:

16.8 / 1 [cpp.predefined]

The following macros must be defined by the implementation:

 __cplusplus 

The name __cplusplus determined by the value 201103L when compiling a C ++ translation unit. 157

157) It is intended that future versions of this standard will replace the value of this macro with a larger value. Inappropriate compilers should use a value of no more than five decimal digits.

So, I think you could do:

 #if defined(__cplusplus) && (__cplusplus >= 201103L) 

But I'm afraid this will not work with pre-standard versions of GCC 0x GCC. Therefore, I probably would use both __GXX_EXPERIMENTAL_CXX0X__ and __cplusplus together:

 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)) 

Compatible with C ++ 0x / C ++ 11

However, this may not be enough to simply determine if C ++ 0x / C ++ 11 support is enabled: C ++ 11 support has changed a lot in all versions of GCC, not only at the core language level, but also at the library level.

It would be best to find the minimum version of GCC that you think is acceptable to support C ++ 11, and combine the above tests with a test for the GCC version, for example:

 #if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ >= 5)) // for GCC 4.7+ 

Switch between boost and std

Now, to switch between boost::shared_ptr and std::shared_ptr , this is a little cumbersome because C ++ 03 does not support template typedef. I for one wrap the necessary 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). I just noticed @ComicSansMS a way to import the correct shared_ptr with a simple directive without using pattern. I don’t know why I didn’t think about it.

However, I stand with how I described the detection of C ++ 0x / C ++ 11 on GCC.

+4
source

All Articles