2

I have a class hierarchy and I want get shared from this and cast it to the specific class type. So I want this:

class A : public std::enable_shared_from_this { std::shared_ptr<A> getSharedFromThis() { return std::static_pointer_cast<A>(shared_from_this()); } }; class B : public A { std::shared_ptr<B> getSharedFromThis() { return std::static_pointer_cast<B>(shared_from_this()); } }; 

In superclass I can write a templated variant but it is still not cool:

template <typename T> std::shared_ptr<T> getSharedFromThis() { return std::static_pointer_cast<T>(shared_from_this()); } 

How can I make it generic so that it will understand that it is in class B and cast to B the shared_ptr and now write the same logic in 100 classes that are in the same hierarchy.

6
  • 1
    Is using the CRTP a reasonable solution? Commented Dec 4, 2015 at 10:21
  • @TartanLlama with CRTP I am going to inherit from the same class in all hierarchy. Commented Dec 4, 2015 at 10:46
  • BTW, if you want to use std::shared_from_this, then you have to derive your class from std::enable_shared_from_this. Commented Dec 4, 2015 at 11:08
  • @Nawaz it is done in my code :) Commented Dec 4, 2015 at 11:09
  • 1
    It does not hurt if you add this to your code-snippet here, otherwise the current form will confuse a lot of readers, and mislead newbies. Commented Dec 4, 2015 at 11:10

2 Answers 2

2

You are looking for covariant return type wise smart pointers. That would be a nice feature, but you cant do it. The only way it could work is having a hierarchical relationship between shared_ptr<A> and shared_ptr<B>, which will not be the case in any near future.

You must either stick to the parent class template or use a wrapper object able to implement the covariant return type paradigm (that would mean careful declarations and possible mistakes due to copypasta).

std::enable_shared_from_this is not used correctly in your example since it is a templated class.

Be careful to use a dynamic_pointer_cast if the getter lays in the parent class.

Sign up to request clarification or add additional context in comments.

Comments

1

It seems your key problem is deducing the type which called the templated getSharedFromThis(). Since the member function is implemented in a base class, it doesn't have any trace of derived class calling it - unless that is somehow specified. Using a non-member function calling the base function will take care of that neatly:

template <typename T> auto getSharedFromThis(T& object) -> decltype(object.template getSharedFromThis<T>()) { return object.template getSharedFromThis<T>()); } 

This way there is no need to write anything for any of derived classes to get a getSharedFromThis() function yielding an appropriately type std::shared_ptr<T>. As a bonus, a similar hierarchy with a base exposing a getSharedFromThis() function can use the same function. You might want to overload the function with a pointer type so you can use getSharedFromThis(this) instead of getSharedFromThis(*this) in member functions.

2 Comments

I don't understand your solution. What is getSharedFromThis that you call in the body of the template function. Please explain you code a bit.
@Narek: the idea is to have a base-class function template getSharedFromThis() which is actually exactly the member you wrote (labeled "not cool") and to use this member from a non-member function template. The implementation of my non-member function just calls that base member (the only quirky thing here is the odd template keyword which is needed because getSharedFromThis is a dependent name).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.