c++c++11smart-pointersc++03

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"?


Solution

  • 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 3:
    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.