class baseを継承したclass derived1とclass derived2があるとしたとき、

std::shared_ptr<base> d1 = std::make_shared<derived1>();
std::shared_ptr<base> d2 = std::make_shared<derived2>();

//自動でstd::shared_ptr<derived1>にキャストされる
auto d1_casted = d1->cast();
//自動でstd::shared_ptr<derived2>にキャストされる
auto d2_casted = d2->cast();

のように自動でダウンキャストしてくれる関数を実装したいと考えているのですがうまくいきません。

試しに上記の機能を実装しようとしてみたのですが、オーバーロード関数の呼び出しの解決ができないとエラーが出てしまいます。何かよい方法はございませんでしょうか。

以下が今の実装です。

#include<type_traits>
#include<typeinfo>
#include<memory>
#include<iostream>

class derived1;
class derived2;

extern void* enabler;

class base
{
public:

    template<typename T, typename std::enable_if<std::is_same<decltype(typeid(std::shared_ptr<derived1>)), decltype(typeid(std::shared_ptr<T>))>::value>::type*& = enabler>
std::shared_ptr<derived1> cast(std::shared_ptr<T> ptr)
{
    return std::static_pointer_cast<derived1>(ptr);
}

template<typename T, typename std::enable_if<std::is_same<decltype(typeid(std::shared_ptr<derived2>)), decltype(typeid(std::shared_ptr<T>))>::value>::type*& = enabler>
std::shared_ptr<derived2> cast(std::shared_ptr<T> ptr)
{
    return std::static_pointer_cast<derived2>(ptr);
}

void print()
{
    std::cout << "base class.\n";
}

};

class derived1 : public base
{
public:

void print()
{
    std::cout << "derived1 class.\n";
}
};

class derived2 : public base
{
public:

void print()
{
    std::cout << "derived2 class.\n";
}
};

int main(int argc, char* argv[])
{
std::shared_ptr<base> d1_base = std::make_shared<derived1>();

auto d1 = d1_base->cast(d1_base);

return 0;
}