4

I have this function that's supposed to generate different derived objs and return as a unique_ptr<base>:

class base {};  // contains pure functions.
class derived1 {}; // reifies that pure iface.
class derived2 {}; // reifies that pure iface.

unique_ptr<base> factory::load(int param)
  {
    switch (param)
      {
      case PARAM_MAIN:
        return new derived1();
        // return std::move(new derived1());

      case PARAM_2:
        return new derived2();

      case ...:
        return new derived...();

      }
  }

there's no way I can get this thing going, even using the std::move. (Also used dynamic_cast, but maybe did it wrong).

This is the error I get: (gcc (GCC) 4.8.1 20130725 (prerelease) on ArchLinux)

could not convert '(std::shared_ptr<base::model>((*(const std::shared_ptr<base::model>*)(& associatedModel))), (operator new(48ul), (<statement>, ((derived1*)<anonymous>))))' from 'derived1*' to 'std::unique_ptr<base>'
            associatedModel));

I hope I've been clear about what I wanna do.

How do I do it? Thanks.

Haix64
  • 806
  • 1
  • 13
  • 21
  • 7
    "*This is the error I get*" Somehow, I don't think that code gives that error. Especially since it mentions `shared_ptr`, which you are *not* using. It seems likely that there's something in your code which you aren't showing us. – Nicol Bolas Aug 17 '13 at 11:54
  • Are `derived1` and `derived2` supposed to inherit from `base`? Because right now you're trying to implicitly cast between orthogonal types, which generally isn't allowed (nor a good idea). – Ponkadoodle Jan 24 '18 at 18:14

2 Answers2

6

You can either do unique_ptr<derived1>(new derived1()); or even better (with C++14) use std::make_unique.

using namespace std;

class base {};  // contains pure functions.
class derived1 {}; // reifies that pure iface.
class derived2 {}; // reifies that pure iface.

unique_ptr<base> factory::load(int param) {
  switch (param) {
    case PARAM_MAIN: return make_unique<derived1>();
    case PARAM_2:    return make_unique<derived2>();
    case ...:        return make_unique<derived...>();
  }
}
Man of One Way
  • 3,904
  • 1
  • 26
  • 41
-7

I solved it this way:

return unique_ptr<base>(dynamic_cast<base*>(std::move(
               new derived1()
       )));

So the point is that it has to be upcasted to base while its still raw, and only then be wrapped in the unique_ptr.

I appreciate simpler answers anyway. Especially those reasoning based on the internals of unique_ptr and the implementation.

Haix64
  • 806
  • 1
  • 13
  • 21
  • 5
    The constructor of `std::unique_ptr` is `explicit`, that's why `return new blah();` doesn't work. `return unique_ptr(new derived1());` works fine. – Xeo Aug 17 '13 at 12:33