yggdrasil yggdrasil - 5 days ago 6
C++ Question

C++ std:.auto_ptr or std::unique_ptr (to support multiple compilers, even old C++03 compilers)?

I'm trying to update some C++ code, I'd like to move toward a more modern code (c++11), but I still need to compile the code with some older compilers (c++03 compliant), because of supported platform constraints.

I know in C++11 compilers std::auto_ptr is deprecated, but because of the older compiler support, I can't just replace them with std::unique_ptr.

Is there a good practice to handle this "old compiler support, but start to move to C++11"?

Answer

As you noted, std::auto_ptr<> has been deprecated in C++11 (Reference).

Moving to c++11 std::unique_ptr<> is the right way, as also stated by Herb Sutter in GotW89:

  1. What’s the deal with auto_ptr?
    auto_ptr is most charitably characterized as a valiant attempt to create a unique_ptr before C++ had move semantics. auto_ptr is now deprecated, and should not be used in new code.
    If you have auto_ptr in an existing code base, when you get a chance try doing a global search-and-replace of auto_ptr to unique_ptr; the vast majority of uses will work the same, and it might expose (as a compile-time error) or fix (silently) a bug or two you didn’t know you had.

Please also note that C++17 is going to remove std::auto_ptr.

I think there may be different ways of solving your problem, the "right" one also depends on how your actual code is written.
A few options are:

Option 1

Use boost::unique_ptr

Option 2

Conditionally use auto_ptr or unique_ptr based on __cplusplus.

class Myclass {
#if __cplusplus < 201103L
std::auto_ptr m_ptr;
#else
std::unique_ptr m_ptr;
#endif
...

This will be scattered in every place where you reference auto_ptr, I don't really like it.
May be look less awkward if all your references to std::auto_ptr are already typedef'ed (just conditionally change the typedef).

Option 3

Conditionally use using and aliasing to "define" auto_ptr (and reference it without std:: namespace).

#if __cplusplus < 201103L
using std::auto_ptr;
#else
template
using auto_ptr = std::unique_ptr;
#endif

Drawback: you keep using "auto_ptr", but in c++11 it means std::unique_ptr.
Really confusing...

Option 3.1

Probably slightly better than option 2:
reverse using aliases and prefer unique_ptr name.

Option 4

Wrap the std:: smart pointer (conditionally auto_ptr or unique_ptr) in your own defined template smart pointer class.
This may be cumbersome and requires search and replacement of all auto_ptr references with your new class.

Other dirty options

Other options involve definitions inside the std:: namespace, which I think is prohibited by the standard,
or using preprocessor #define to ...ehm... "rename" unique_ptr to auto_ptr just for old C++03 compilers.