As long as you've tested with every possible combination of runtime factors/variables/inputs, sure. As mentioned in the comments, this would be akin to removing assertions.
There's nothing in the language that would make this inherently unsafe, given the requisite assurances that your casts will always be correct. It does feel inherently unsafe, though, in that you could probably never make such a guarantee.
Update
Konstantin has proved that when dealing with multiple inheritance this technique will only work for single steps up/down the inheritance tree1.
struct A1 { virtual ~A1() {} };
struct A2 { virtual ~A2() {} };
struct A3 { virtual ~A3() {} };
struct B : A1, A2 {};
struct C : A1, A3, A2 {};
int main() {
A1* a1 = (rand() < RAND_MAX / 2 ? (A1*)new B : (A1*)new C);
A2* p1 = dynamic_cast<A2*>(a1);
// ^ succeeds, but is a cross-cast
// A2* p2 = static_cast<A2*>(a1);
// ^ ill-formed
A2* p3 = static_cast<A2*>(static_cast<B*>(a1));
// ^ must chain, instead.
// but p3 is invalid because we never
// checked that `dynamic_cast<B*>(a1)` is valid.. and it's not
// Instead, let's expand the `dynamic_cast`s into a chain, too:
A2* p3 = dynamic_cast<B*>(a1);
A2* p4 = dynamic_cast<A2>*(a1);
// ^ p3 fails, so we know that we cannot use `static_cast` here
}
So, you can replace your dynamic_cast
s with static_cast
s iff:
- Each
dynamic_cast
performs only a single step up or down;
- Each
dynamic_cast
is known to always succeed.
1 Actually this is a bit of a simplification as, for example, downcasts will work for any number of steps. But it makes a good rule of thumb.