#include <algorithm>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>


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

class B : public A
{
public:
	void doReallyCoolStuff();
}; 

void doCoolStuff(std::weak_ptr<A> obj)
{
	std::cout << "cool A\n";
}

void doCoolStuff(std::weak_ptr<B> obj)
{
	std::cout << "cool B\n";
 doCoolStuff(std::static_pointer_cast<A>(obj.lock()));
}

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

int main()
{
	auto b = std::make_shared<B>();
	b->doReallyCoolStuff();
}