5

I have:

class A : public std::enable_shared_from_this<A>
{...};

class B : public A
{...}; 

void doCoolStuff(std::weak_ptr<A> obj)
{...}

void doCoolStuff(std::weak_ptr<B> obj)
{
 ...
 doCoolStuff(std::static_pointer_cast<A>(obj.lock())); (1)
}

And then in B function:

void B::doReallyCoolStuff()
{
 doCoolStuff(std::static_pointer_cast<B>(shared_from_this())); (2)
}

So problems are:

  1. Compiler error: error C2440: 'static_cast' : cannot convert from 'B *const ' to 'A *'
  2. Compiler error: error C2668: ambiguous call to overloaded function

I don't understand how to resolve either of them, because:

  1. I think it's somehow connected with shared_from_this, because this is const pointer. But I don't know how to handle this situation without const_cast.
  2. I don't know if functions can be overloaded by different types of weak pointers.

Build environment: MSVS 2013 express

Please, help. Thank you

1
  • My bad, sorry, I'm trying to make example of code as simple as I can. Commented Sep 17, 2014 at 8:04

2 Answers 2

6

As for problem (2), you can of course overload like this. But the problem is that you're calling the function with the type std::shared_ptr<B>. This requires an implicit conversion to a std::weak_ptr, and it can convert to both std::weak_ptr<A> and std::weak_ptr<B>. Both of these are implemented by an implicit conversion constructor inside std::weak_ptr, which means none of them is better than the other. Hence the ambiguity.

To solve this, you can specify the type explicitly:

void B::doReallyCoolStuff()
{
    doCoolStuff(std::weak_ptr<B>(std::static_pointer_cast<B>(shared_from_this())));
}

Live example

Alternatively, you can provide overloads of doCoolStuff taking std::shared_ptr.

As the live example above shows, I wasn't able to reproduce issue (1).

1
  • @DoctorMoisha Can you provide an MCVE, i.e. code which one could just copy-paste into a file, build and get the error? Without that, since I can't reproduce it, it's impossible to say if it's an issue with your compiler or something you haven't shown. Commented Sep 17, 2014 at 11:37
2

You may like to review the arguments to your functions.

Functions only need to accept a smart-pointer if they need to keep the pointer somewhere after return. Otherwise functions should accept references or plain pointers.

According to Herb Sutter in Back to the Basics! Essentials of Modern C++ Style - Herb Sutter - CppCon 2014 functions accepting smart-pointers (by value or by reference) is an anti-pattern, unless those function needs to store, change or let go of a reference:

  • Don’t use owning raw *, new, or delete any more, except rarely inside the implementation details of low-level data structures.

  • Do use non-owning raw * and &, especially for parameters.

  • Don’t copy/assign refcounted smart pointers, including pass-by-value or in loops, unless you really want the semantics they express: altering object lifetime.

2
  • 1
    This is a comment instead of an answer.
    – Casey
    Commented Sep 17, 2014 at 16:05
  • @Casey It's not best answer, but I think it's still an answer, because OP asks how to resolve problems and getting rid of smart-pointers as function arguments is the way to resolve them.
    – mip
    Commented Sep 17, 2014 at 20:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.