Рассмотрим эту иерархию классов:
struct Animal { virtual ~Animal(); };
struct Cat : virtual Animal {};
struct Dog final : virtual Animal {};
Я понимаю, что размещение final на class Dog гарантирует, что никто не сможет создать класс, наследующий от Dog, что, в свою очередь, означает, что никто не может создать класс, который IS-A Dog и IS -A Cat.
Рассмотрим эти два dynamic_cast s:
Dog *to_final(Cat *c) {
return dynamic_cast<Dog*>(c);
}
Cat *from_final(Dog *d) {
return dynamic_cast<Cat*>(d);
}
GCC, ICC и MSVC игнорируют квалификатор final и генерируют вызов __dynamic_cast; это несчастливо, но не удивительно.
Что меня удивило, так это то, что Clang и Zapcc генерируют оптимальный код для from_final ( "always return nullptr" ), но генерируют вызов до __dynamic_cast для to_final.
Является ли это действительно упущенной возможностью оптимизации (в компиляторе, где, очевидно, кто-то приложил некоторые усилия для соблюдения квалификатора final в приведениях) или оптимизация невозможна в этом случае по какой-то тонкой причине, что я все еще не вижу