1

I have one implementation class and one wrapper class, and I want to access to implementation class instance through wrapper class with structure dereference (->) operator. So far, no problem.

class Implementation
{
  public:
    doSomething();
}

class Wrapper
{
  public:
    Implementation* operator->() {
      return _implPtr.get();
    }
  private:
    std::shared_ptr<Implementation> _implPtr;
}

It works when I use it like below:

Wrapper wrapper;
wrapper->doSomething();

But when I use the wrapper class with unique_ptr, compiler throws an error:

auto wrapper = std::make_unique<Wrapper>();
wrapper->doSomething();

The error is "'class Wrapper' has no member named 'doSomething'".

How can I access to the implementation class in this scenario?

brakulla
  • 23
  • 4
  • `_implPtr->get();` -- Shouldn't that be `_implPtr.get();`? – PaulMcKenzie Apr 13 '20 at 23:30
  • 2
    You can’t. `unique_ptr` adds an indirection — by design! Your code also doesn’t work with a `Wrapper*` object, for the same reason. Use `(*wrapper)->doSomething`. – Konrad Rudolph Apr 13 '20 at 23:31
  • 2
    The shown code is obviously not the real code with the compilation error, so any speculation as to the cause of the compilation error will be nothing more than speculation, and a random guess. – Sam Varshavchik Apr 13 '20 at 23:32
  • @PaulMcKenzie yes, my mistake while summarising – brakulla Apr 13 '20 at 23:41
  • @SamVarshavchik I can't share the real code since the real classes are huge and I'm not allowed to share them – brakulla Apr 13 '20 at 23:42

1 Answers1

2

std::unique_ptr (and std::shared_ptr) has its own operator-> to return the pointer it is holding.

Your failing code is essentially doing this:

auto wrapper = std::make_unique<Wrapper>();
//wrapper->doSomething();
Wrapper *ptr = wrapper.operator->();
ptr->doSomething(); // ERROR!

Indeed, there is no doSomething() method in your Wrapper class.

To do what you are attempting, you need to dereference the Wrapper* pointer to access the actual Wrapper object, then you can call its own operator-> to access its Implementation* pointer, eg:

auto wrapper = std::make_unique<Wrapper>();
(*wrapper)->doSomething();

Which is basically doing this:

auto wrapper = std::make_unique<Wrapper>();
//(*wrapper)->doSomething();
Wrapper &ref = wrapper.operator*();
Implementation *impl = ref.operator->();
impl->doSomething(); // OK!
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770