class base {
    int a;
protected:
    template<class T>
    class derived;
public:
    base() {}
    virtual ~base() {}
    virtual void func() {}
    static base* maker();
};

template <class T>    
class base::derived 
    : public base
{
public: 
    derived() {}
    virtual ~derived() {}
    virtual void func() {
        this->~derived(); //<--is this legal?
        new (this) derived<int>(); //<--is this legal?
    }
};

base* base::maker() {
    return new derived<double>();
}

int main() {
    base* p = base::maker(); //p is derivedA<double>
    p->func(); //p is now derivedA<int>
    delete p; //is the compiler allowed to call ~derived<double>()?
}

This can be a Short, All-in-one, Correct (Compilable), Illustration of my code (that is essentially reinventing any_iterator for my very own growth).

The question reduces lower to: could it be undefined behavior to eliminate this and rebuild this having a different type virtually based on exactly the same base, when neither has any extra people within the shared base? Particularly, are compilers permitted to call keep an eye on the static type, or perhaps is that technically nonconforming?

[EDIT] Multiple people stated that compilers may call the wrong destructor if derivedA is produced around the stack. (1) I can not find anything within the standard that enables compilers to do this. (2) Which was apart from things i intended by my question, and so i have transformed the code to exhibit that derived cannot go around the stack. base can nonetheless be around the stack though.

I believe that's clearly not OK.

Like a preface, and object's lifetime can certainly be ended by calling the destructor, but you are only permitted (and needed) to create a brand new object of the identical type instead:

{
  Foo x;
  x.~Foo();
  ::new (&x) Foo;
}  // x.~Foo() must be a valid call here!

Keep in mind that at scope's finish the destructor is going to be invoked!

However in your situation you are creating an entirely different object:

::new (&x) Bar;   // Bar = DerivedA<int>

Clearly if sizeof(Bar) surpasses sizeof(Foo) this can't be OK.

(Possibly if you're able to make additional guarantees around the object dimensions, and also on the alignment guarantees, we are able to consider this.)

Update: Even when you are thinking, OK, so individuals types are based on exactly the same base, so invoking the destructor brings virtual happiness, I am still confident that this is a breach. Within this static setting, the compiler might resolve the virtual call statically, so you are smashing the compiler's presumptions should you alter the dynamic kind of the one thing pointed to by &x.

Update 2: Another thought on a single matter: The static type of *&x is famous, and i believe you need to respect that. Quite simply, the compiler doesn't have reason to element in the chance that the static type of the local variable changes.