In most respects the std::unique_ptr
was made to be drop in (but safer) replacement for std::auto_ptr
, so there should be very few (if any) code changes required other than (as you ask) directing the code to use either unique_ptr
or auto_ptr
.
There a few ways to do this (and each comes with its own list tradeoffs) below. Given the code sample provided, I would favour either of the first two options.
Option 1
#if __cplusplus >= 201103L
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif
Tradeoffs;
- You introduce the
auto_ptr
name into the global namespace; you can mitigate this by defining it in your own "private" namespace
- Once you migrate to C++17 (I believe
auto_ptr
will be completely removed) you can more easily search and replace
Option 2
template <typename T>
struct my_ptr {
#if __cplusplus >= 201103L
typedef std::unique_ptr<T> ptr;
#else
typedef std::auto_ptr<T> ptr;
#endif
};
Tradeoffs;
- Probably more cumbersome to work with as all the current
auto_ptr
references need to be changed in the code to something like my_ptr<T>::ptr
- Better safety because the names are not being introduced into the global namespace
Option 3
Somewhat controversial, but if you are prepared to put up with the caveats of having a std
class as a base
#if __cplusplus >= 201103L
template <typename T>
using my_ptr = std::unique_ptr<T>;
#else
template <typename T>
class my_ptr : public std::auto_ptr<T> {
// implement the constructors for easier use
// in particular
explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {}
};
#endif
Tradeoffs;
- Don't try to use the inherited class where a virtual base (in particular w.r.t. the non-virtual destructor) would be expected. Not that this should be an issue in the case - but be aware of it
- Again, code changes
- Potential namespace mismatches - it all depends on how the pointer class is used to begin with
Option 4
Wrap the pointers in a new class and aggregate the required functions to the member
template <typename T>
class my_ptr { // could even use auto_ptr name?
#if __cplusplus >= 201103L
std::unique_ptr<T> ptr_;
#else
std::auto_ptr<T> ptr_;
#endif
// implement functions required...
T* release() { return ptr_.release(); }
};
Tradeoffs;
- A little extreme when all you really want is to "swap" the implementations out
auto_ptr
scoped (i.e.std::auto_ptr
), do they need to be or can the smart pointer be obtained from some other namespace?Foo::Initialize
intoFoo::Foo
.