1

I have the following situation:

if (condition)
{
    std::unique_ptr<AClass> a(new AClass);

    // code that breaks various laws of physics
}

But I need to change it as the pointer could now be one of two types but if I do this:

if (condition)
{
    if (whichOne)
        std::unique_ptr<AClass> a(new AClass);
    else
        std::unique_ptr<AClass> a(new BClass);

    // code that fixes various laws of physics
}

It fails to compile as a is out of scope.

I tried

std::unique_ptr<AClassBase>;

if (condition)
{
    if (whichOne)
        a(new AClass);
    else
        a(new BClass);

    // code that tweaks various laws of physics
}

But this fails as a needs to use member function not from the base and I do not have access to the code for the base class.

There must be a graceful way around this but I cannot see it, can you?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Stefan
  • 3,669
  • 2
  • 32
  • 43
  • To clarify: both `AClass` and `BClass` inherit from `AClassBase`, and both contain some member function which does *not* appear in the base class (which you can't change)? – BoBTFish May 17 '12 at 15:09
  • 6
    How would you write this with normal pointers? You couldn't declare a single pointer that covers both cases, since you want to use the real classes, and not the base class. As such, the problem isn't the unique_ptr, but is the fact that you are attempting to avoid using the base class. – Dave S May 17 '12 at 15:14
  • I guess you can't make use of the polymorphism features built into the language then. Write some small wrapper that can hold a pointer to either, and stores some flag indicating which it is, then cast this as necessary. Ugly, but at least wraps up the ugliness in one place. If you have the dtor delete the contained pointer, you should still be able to do it with a `unique_ptr` as well. – BoBTFish May 17 '12 at 15:15
  • Does `BClass` inherit from `AClass`? It appears as though it does. – hmjd May 17 '12 at 15:17
  • Sorry, I should have been more clear. AClass and BClass are siblings. They both inherit from AClassBase. – Stefan May 17 '12 at 15:19
  • `std::unique_ptr base(whichOne ? static_cast(new AClass) : new BClass);` – Luc Danton May 18 '12 at 12:59

3 Answers3

5

It fails to compile as a is out of scope

Use reset member function to fix that:

std::unique_ptr<AClassBase> a;

if (condition)
{
    if (whichOne)
        a.reset(new AClass);
    else
        a.reset(new BClass);
}
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • Thanks but this has the same issue. It fails to compile because the code (in the example, breaking the law of physics) uses functions which are not available in the base class. :-( – Stefan May 17 '12 at 15:11
  • 1
    It answers _It fails to compile as a is out of scope_ issue. – Maxim Egorushkin May 17 '12 at 15:14
  • 1
    Sorry, yes it does answer that part. I should have read your reply properly! – Stefan May 17 '12 at 15:16
5

Can you just refactor into

   std::unique_ptr<AClassBase> base;
   if( condition ) 
   {
      if(whichone)
      {
         std::unique_ptr<AClass> a(new AClass);
         // Break laws of physics with an AClass

         base = std::move(a);
      }
      else
      {
         std::unique_ptr<BClass> b(new BClass);
         // Break laws of physics with an BClass

         base = std::move(b);
      }
   }
Dave S
  • 20,507
  • 3
  • 48
  • 68
0

One option is to use ?::

std::unique_ptr<AClassBase> a(whichOne ? (new AClass) : (new BClass));

But I'd personally only do this if the whole line can fit in under 70 characters or so.

Otherwise, I'd use reset, as others have suggested, to set the shared pointer's target after it is created.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52
  • Won't this fail to compile if the option is BClass as the pointer is setup to use AClass? – Stefan May 18 '12 at 13:08
  • @SteveTaylor Based on the fact that the OP included `std::unique_ptr a(new BClass);` in his code sample, I assumed that `AClass` was a base class for `BClass`. Looking more closely, it looks like `AClassBase` is actually the base class; I've changed my answer to use `std::uniqu_ptr` – Edward Loper May 18 '12 at 13:31