6

Taken from: http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/

Why should we write:

auto pb = unique_ptr<base>{ make_unique<derived>() };

Instead of just:

auto pb = make_unique<derived>();

My only guess is that if we want auto, we need to help it deduce the right type (base here).

If so, then for me this would be really doubtful merit.. to type auto and then type a lot of initialization on the right side of = ..

What am I missing?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Yanko
  • 784
  • 8
  • 16
  • 1
    Erm, Why? Because you want the first thing and not the second? They are not equivalent. (Check `decltype(pb)`) – R. Martinho Fernandes May 27 '13 at 13:48
  • 1
    one thing is clear here, if you have a smart_pointer of derived you cannot easily cast it to base. because unlike base *x; and derived *y; there is no relation in the type hierarchy. – Alexander Oh May 27 '13 at 13:51
  • 4
    Just wondering, would `unique_ptr pb = make_unique();` be simpler? Because `auto` exists doesn't mean we must use it. – FredericS May 27 '13 at 14:11
  • @FredericS: It would be slightly shorter, more familiar to people not used to C++11, and less explicit since it involves an implicit conversion. Whether that makes it "simpler" or not is an aesthetic judgement. – Mike Seymour May 27 '13 at 14:13
  • I still like `auto pb = unique_ptr(new derived());` for clarity. – Sander De Dycker May 27 '13 at 14:23
  • 1
    @SanderDeDycker even better with uniform-init: `{}` – emesx May 27 '13 at 15:20

3 Answers3

10

Well, the point is that the first option makes pb a unique_ptr<base>, while the second option makes pb a unique_ptr<derived>. Whether both are correct or not in your situation depends on what you have to do with pb - but definitely the two are not equivalent.

If the relevant part of your program needs to work with a unique_ptr<base> (perhaps because later on you are going to let it to point to an instance of a different derived class), then the second solution is simply not viable.

For example:

auto pb = unique_ptr<base>{ make_unique<derived>() };
// ...
pb = make_unique<derived2>(); // This is OK
// ...

Whereas:

auto pb = make_unique<derived>();
// ...
pb = make_unique<derived2>(); // ERROR! "derived2" does not derive from "derived"
// ...
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
6

My only guess is that if we want auto, we need to help it deduce the right type (base here).

That's exactly right. Without the conversion, pb would be a pointer to derived which might not be what you want. For example, you couldn't reassign it to own a base or other derived-class object.

If so, then for me this would be really doubtful merit..

I'm inclined to agree. The author notes in a comment that he did it because he likes to use type deduction as much as possible, with explicit conversions where necessary. Time will tell whether that style becomes commonplace.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
4
auto pb = unique_ptr<base>{ make_unique<derived>() };

the above creates a unique_ptr<base> that contains a derived.

auto pb = make_unique<derived>();

the above creates a unique_ptr<derived> that contains a derived.

While replacing the 2nd with the 1st could be acceptable, they actually do different things.

As an aside, searching for make_unique in the linked-to article results in someone answering this very question there.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524