Filipp
Filipp

Reputation: 2040

How can I form a `final` reference to a non-final class?

final is an excellent keyword. It lets me prevent inheritance from a class. It also lets the compiler skip the runtime dispatch mechanisms when calling virtual functions or accessing virtual bases.

Suppose now that I have some non-final class T with virtual functions and/or base classes. Suppose also that I have a reference to an instance of this class. How could I tell the compiler that this particular reference is to the fully-derived complete object, and not to a base sub-object of a more derived type?

My motivations are classes like optional and vector. If I invoke optional<T>::operator*(), I get a T&. However, I know with certainty that this reference really is a T, not some more derived object. The same applies to vector<T> and all the ways I have of accessing its elements.

I think it would be a great optimization to skip the dynamic dispatch in such cases, especially in debug mode and on compilers not smart enough to look through the optional and vector implementations and devirtualize the calls.

Upvotes: 2

Views: 183

Answers (1)

Davis Herring
Davis Herring

Reputation: 39818

Formally, you can do this:

void final(A &a) {
  static_cast<A*>(dynamic_cast<void*>(&a))->foo();
}

dynamic_cast<void*> returns a pointer to the most-derived type (and static_cast from void* cannot select a polymorphic base class), so the compiler can know that A::foo is being called. However, compilers don’t seem to take advantage of this information; they even generate the obvious extra instructions to actually perform the dynamic cast (even though it’ll of course be undefined behavior if it fails).

You can, certainly, devirtualize yourself by actually writing a.A::foo() whenever verbosity and genericity permit.

Upvotes: 2

Related Questions