Is there any contraindications to use a
reinterpret_casthere ?
Don't do that; it will give undefined behaviour.
Typically, the base sub-objects are stored at different locations within the complete object, so that cast will end up pointing to the wrong location. You might find that it "works" by accident with these empty base classes, since they might (or might not) end up at the same location; but you certainly can't rely on that behaviour.
Should I mandatory use
dynamic_cast?
If you don't know the common derived type (C12) at compile time, then that's the only sensible option. Note that it requires polymorphic classes (which is the case here).
If you do know the common derived type, then you can convert via that using static_cast:
I1 * p1 = static_cast<I1*>(static_cast<C12*>(p2));