1

I have some code that uses std::auto_ptr and gives ugly warnings about deprecated std::auto_ptr (GCC 4.7.1 on Suse Linux 12.2) when compiling.

So I have tried the following (since I found some source that states std::unique_ptr should be the appropriate equivalent)

template<typename T>
struct AutoPtr
{
#ifdef COMPILE_FOR_CX11
    typedef std::unique_ptr<T> Type;
#else
    typedef std::auto_ptr<T> Type;
#endif
};

and replaced any references to std::auto_ptr<T> with AutoPtr<T>::Type, but got compile errors when using this option.

I'm pretty sure I want to use something like std::auto_ptr at these pieces of code and I'm aware about the culprits and deficiencies of it. The errors I get seem to correlate about construction issues when std::unique_ptr is used.

As a side note: The final class used for construction is an inheriting type of T, the code looks like:

class MockClass;

class Client
{
public:
    Client();
    Client(const Client& rhs);

private:
    mutable AutoPtr<MockClass>::Type embeddedMock;
};

Client::Client()
: embeddedMock(new ::testing::NiceMock<MockClass>())
//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Getting errors here!
{
}


Client::Client(const Client& rhs)
: embeddedMock(rhs.embeddedMock)
{
}

So what's a full compliant smart pointer from the c++11 set, I can use here?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 2
    The wrapper class is a bit pointless. You can just say `#define AutoPtr std::auto_ptr` etc. and then say `AutoPtr`. – Kerrek SB Jul 12 '13 at 21:21
  • 1
    What's the compile error? – small_duck Jul 12 '13 at 21:22
  • 1
    It should be `mutable AutoPtr::Type embeddedMock;` – Andy Prowl Jul 12 '13 at 21:22
  • @AndyProwl Yes, was a 'typo'! Edited that ... – πάντα ῥεῖ Jul 12 '13 at 21:24
  • 2
    @g-makulik: It seems to work [here](http://coliru.stacked-crooked.com/view?id=dea794f30cda8cfa4c504829545cf5d3-9a9914b3e2b7ed07c206d6accecccdb6) – Andy Prowl Jul 12 '13 at 21:25
  • @KerrekSB I'm just cautious about needing more adaptions besides the type ... – πάντα ῥεῖ Jul 12 '13 at 21:36
  • @DavidBrown Not sure! I've replicated the code to reduce to the pattern. But I thought it was at the line with the `new` ... – πάντα ῥεῖ Jul 12 '13 at 21:38
  • @AndyProwl Sorry for all the hype! Yes, when I remove 'typos' in my real code it compiles well, as you expected. What should we do with this question? Is there already a canonical question about `std::auto_ptr` porting to `std::unique_ptr` around? – πάντα ῥεῖ Jul 12 '13 at 22:14
  • 1
    @AndyProwl: Ouch! `mutable`? ouch! That is abusing the intent of `mutable` to work around a different limitation of the design. Two wrongs don't make one right, even if it compiles. – David Rodríguez - dribeas Jul 12 '13 at 22:37
  • @DavidRodríguez-dribeas: I just meant to fix the error with the template instantiation, not to provide an answer :) – Andy Prowl Jul 12 '13 at 22:39
  • @DavidRodríguez-dribeas Finally I have removed those copy constructors now, since they're not needed at all. No need for mutable then (there's no assignment operator defined either) ... (And yes: Ouch! Didn't feel good with this, was an XYZ problem) – πάντα ῥεῖ Jul 12 '13 at 22:55
  • The fully compliant smart pointer for `std::auto_ptr` is `std::auto_ptr`. It's deprecated, which means that it **might** go away in some future version of the standard. Until that happens, it's part of the standard. That said, if you use it you have to live with it's somewhat quirky behavior. But that's nothing new. – Pete Becker Jul 12 '13 at 23:51
  • @PeteBecker Could you clarify about the differences now, and how a surrogate should be used/implemented? – πάντα ῥεῖ Jul 13 '13 at 00:03

1 Answers1

9

unique_ptr is the C++11 replacement facility for auto_ptr. However, it's not a drop-in replacement, since auto_ptr had transfer-of-ownership-on-copy semantics and unique_ptr forces you to transfer ownership explicitly. When you have something like this:

auto_ptr<Foo> x(new Foo());
// ...
auto_ptr<Foo> y = x;
// ...
bar( y ); // copies y into bar(), transferring ownership

. . . to use unique_ptr, you would need to add move() to the ownership-transfer sites:

unique_ptr<Foo> x(new Foo());
// ...
unique_ptr<Foo> y = move(x);
// ...
bar( move(y) );

EDIT:

Without knowing what specific error you're getting, it's hard to tell why your default constructor is failing to compile. However, your copy constructor should fail to compile with unique_ptr unless move is added.

Adam H. Peterson
  • 4,511
  • 20
  • 28
  • But that what's the purpose of the `mutable` statement was for. I've shortly seen an answer from a reputable SO member that showed how to use transferring ownership of `std::unique_ptr` explicitly, which would be compliant with `std::auto_ptr`. Introducing move semantics (for code that should compile well for c++ old and cx11 standards) isn't much of a help here :( – πάντα ῥεῖ Jul 12 '13 at 21:34
  • 1
    @g-makulik, right, missed the `mutable` part. Sorry. (Answer edited to correct the copy constructor reference.) If you want to make code that works under C++11 and C++98, you can always introduce a dummy `move`-type operation that compiles out under C++98. I.e. something like: `#ifdef CPP11`|`#define MOVE(X) ::std::move(X)`|`#else`|`#define MOVE(X) X`|`#endif` – Adam H. Peterson Jul 12 '13 at 21:37