Q: Switch Derived class of a shared pointer to base class I am currently trying to switch the type of a derived class stored in a shared pointer to base class.
The problem is that the Derived class inherit from the Base class and is also templated as follow:
Base class:
#define PRINT(s) std::cout << s << std::endl

class Base {
public:
    Base() : m_a(1) {}
    virtual ~Base() = default;
    virtual void print() { PRINT("BASE"); }

    int m_a;
};

The derived class depend on an enumeration template:
enum eType { e0, e1 };

template<eType et>
class Derived : public Base { };

template<>
class Derived<e0> : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};

template<>
class Derived<e1> : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

My objective is to have a shared pointer to the Base class so it would be possible to switch from the 2 derived classes as follow:
int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> ();

    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();

    std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> ();

    *sp_01 = *sp_10;

    sp_01->print();
    sp_10->print();
}

The only problem as on the line *sp_01 = *sp_10; I expect that the pointer to base class switch from the derived type Derived<e0> to the derived type Derived<e1>. However in my example I get a different result for the line sp_01->print(); and the line sp_10->print(); indicating that sp_01 stays as a Derived<e0> type.
I want to avoid sp_01 = sp_10; because it will change the pointer. In the above example, it would lead to sp_00 != sp_01 and I want both sp_00 and sp_01 to share the same object.
I tried to replace the template derived class by a non template derived class as follow:
class Derived_e0 : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};
class Derived_e1 : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

and the following code give the same result as the one with template.
int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived_e0> ();

    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();

    std::shared_ptr<Base> sp_10 = std::make_shared<Derived_e1> ();

    *sp_01 = *sp_10;

    sp_01->print();
    sp_10->print();
}

So my question is, how to switch the derived object pointed by a shared pointer without changing the shared_ptr itself (which is used in other part of the program ?)
Thanks, if you need any more information, please let me know

A: You can dynamic_cast the raw pointer; something like
Derived* t = dymanic_cast<Derived*>(sp_00.get())

And you'll get NULL if it can't be cast, or a valid pointer if it can.  That said, this requires RTTI to be built in, which will make your binary bigger, and needing to do this at all is a sign that your design isn't right.

A: You cannot change the runtime type of sp_01 without re-assigning it because you cannot assign Derived<e1> to Derived<e0> (think of what would happen if these do not have the same size - you have allocated enough size for a Derived<e0>, not for a Derived<e1>!).
In my opinion, your design (or what you are trying to do with it) is flawed somewhere. However, if you really want to keep a "link" between sp_00 and sp_01, you probably need another "level" of pointer:
int main() {
    std::shared_ptr<Base> *psp_01;

    std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> ();
    psp_01 = &sp_00;

    (*psp_01)->print();

    std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> ();
    psp_01 = &sp_10;

    (*psp_01)->print();
    sp_10->print();
}

But again, I would analyze my design twice before using this.
