CXX95 Telegram 94
#madskillz

Напиши свой собственный RTTI 🖱

RTTI (run-time type information) это некая информация о всех виртуальных классах, которая попадает в бинарник программы.
Благодаря этому работают dynamic_cast<> (приведение типа в run-time) и typeid.
Генерацию RTTI можно выключить флагом компиляции -fno-rtti.

Пусть у нас есть указатель X* x (или ссылка X& x). Указатель может указывать на объект с типом не X (но это обязательно будет тип-потомок X).

Есть три варианта приведений типа X к типу Y (тип Y тоже не обязательно реальный тип объекта):

1️⃣Upcast: Y - класс-предок X.
Для этого не требуется никакого RTTI. Такое приведение всегда возможно. Можно было бы обойтись static_cast<> (приведение типа в compile-time).

2️⃣ Downcast: Y - класс-потомок X.
В этом случае обычно используют dynamic_cast<>. Если окажется, что тип объекта не Y (или не какого-то потомка Y), то приведения не случится.

Интересно, что если программист совершенно уверен, что приведение возможно, то можно использовать static_cast<> и не делать run-time проверку. Если окажется, что он был не прав, то получится undefined behaviour 😁

3️⃣ Sidecast: X и Y никак не связаны между собой.
Такое возможно, если X* указывает на объект класса Z:
class Z : public X, public Y {...};
Такие касты dynamic_cast<> тоже умеет делать.
Скорее всего sidecast значит, что в программе есть серьезные ошибки дизайна 🧐

Некоторые проекты не используют "официальный" RTTI 😡
Почему так происходит, на примере очень популярных проектов:

1️⃣ Protobuf: вынужденная поддержка проектов с -fno-rtti.

В protobuf есть базовый для всех "месседжей" класс google::protobuf::Message.

Чтобы попробовать сделать downcast от базового класса до класса "месседжа", можно использовать функцию DynamicCastToGenerated.
Как видно по исходнику, если уж нельзя вызвать dynamic_cast<>, то используется костыль - суррогат RTTI: сравнение ссылки на "рефлексию" (уникальное описание "месседжа"). Эту ссылку возвращает виртуальный метод.

Какие ограничения этого подхода: С -fno-rtti доступен только downcast строго на указанный класс - потомок класса Message.

2️⃣ LLVM: своя реализация RTTI для быстродействия.

Clang и LLVM имеют большую иерархию типов и делают огромную кучу проверок на типы. Большая часть кода в компиляторах (оптимизации, кодогенерация, ...) завязана на поиск специфических паттернов и операциях на них. Для этого необходимо проверять тип объектов в овер9000 местах, поэтому быстродействие dynamic_cast становится узким местом.

А быстродействие у dynamic_cast сравнительно плохое. Он должен делать обход иерархии наследования и вычисляет путь обхода динамическим образом. Это на несколько порядков медленнее, чем просто вызвать виртуальный метод и что-то сравнить.

В документации есть крутая статья, как сделать свой RTTI "почти как в LLVM" - How to set up LLVM-style RTTI for your class hierarchy. Для этого заводится специальный enum, и каждый класс реализует статический метод classof. Вместо обхода иерархии наследования делается один вызов виртуального метода!

Какие ограничения этого подхода: Дополнительный код - enum, статический метод в каждом классе. Нужно следить за тем, чтобы соответствие между enum и классами не разломалось (хотя тут могут помочь кодогенераторы). Эта схема работает, только если иерархия классов известна заранее (стандартный C++ RTTI такого не требует).

Всего известно три главных аргумента "против RTTI":
🅱️ Занимает память в бинарнике - очень сомнительный аргумент. RTTI не требует столько памяти, чтобы это стало заметно, по крайней мере в 2023 году.
🅱️ Медленно работает - хороший аргумент, если dynamic_cast<> является узким местом в программе. Но это должна быть специфическая программа, как поиск паттернов в структурах с большой иерархией классов... (например, компилятор C++)
🅱️ Его использование - ошибка дизайна - неожиданный аргумент, но именно по этой причине RTTI запрещен в Google C++ Style Guide. По ссылке есть описание "почему это плохо". Конечно, из каждого правила есть исключение.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🖕1



tgoop.com/cxx95/94
Create:
Last Update:

#madskillz

Напиши свой собственный RTTI 🖱

RTTI (run-time type information) это некая информация о всех виртуальных классах, которая попадает в бинарник программы.
Благодаря этому работают dynamic_cast<> (приведение типа в run-time) и typeid.
Генерацию RTTI можно выключить флагом компиляции -fno-rtti.

Пусть у нас есть указатель X* x (или ссылка X& x). Указатель может указывать на объект с типом не X (но это обязательно будет тип-потомок X).

Есть три варианта приведений типа X к типу Y (тип Y тоже не обязательно реальный тип объекта):

1️⃣Upcast: Y - класс-предок X.
Для этого не требуется никакого RTTI. Такое приведение всегда возможно. Можно было бы обойтись static_cast<> (приведение типа в compile-time).

2️⃣ Downcast: Y - класс-потомок X.
В этом случае обычно используют dynamic_cast<>. Если окажется, что тип объекта не Y (или не какого-то потомка Y), то приведения не случится.

Интересно, что если программист совершенно уверен, что приведение возможно, то можно использовать static_cast<> и не делать run-time проверку. Если окажется, что он был не прав, то получится undefined behaviour 😁

3️⃣ Sidecast: X и Y никак не связаны между собой.
Такое возможно, если X* указывает на объект класса Z:

class Z : public X, public Y {...};
Такие касты dynamic_cast<> тоже умеет делать.
Скорее всего sidecast значит, что в программе есть серьезные ошибки дизайна 🧐

Некоторые проекты не используют "официальный" RTTI 😡
Почему так происходит, на примере очень популярных проектов:

1️⃣ Protobuf: вынужденная поддержка проектов с -fno-rtti.

В protobuf есть базовый для всех "месседжей" класс google::protobuf::Message.

Чтобы попробовать сделать downcast от базового класса до класса "месседжа", можно использовать функцию DynamicCastToGenerated.
Как видно по исходнику, если уж нельзя вызвать dynamic_cast<>, то используется костыль - суррогат RTTI: сравнение ссылки на "рефлексию" (уникальное описание "месседжа"). Эту ссылку возвращает виртуальный метод.

Какие ограничения этого подхода: С -fno-rtti доступен только downcast строго на указанный класс - потомок класса Message.

2️⃣ LLVM: своя реализация RTTI для быстродействия.

Clang и LLVM имеют большую иерархию типов и делают огромную кучу проверок на типы. Большая часть кода в компиляторах (оптимизации, кодогенерация, ...) завязана на поиск специфических паттернов и операциях на них. Для этого необходимо проверять тип объектов в овер9000 местах, поэтому быстродействие dynamic_cast становится узким местом.

А быстродействие у dynamic_cast сравнительно плохое. Он должен делать обход иерархии наследования и вычисляет путь обхода динамическим образом. Это на несколько порядков медленнее, чем просто вызвать виртуальный метод и что-то сравнить.

В документации есть крутая статья, как сделать свой RTTI "почти как в LLVM" - How to set up LLVM-style RTTI for your class hierarchy. Для этого заводится специальный enum, и каждый класс реализует статический метод classof. Вместо обхода иерархии наследования делается один вызов виртуального метода!

Какие ограничения этого подхода: Дополнительный код - enum, статический метод в каждом классе. Нужно следить за тем, чтобы соответствие между enum и классами не разломалось (хотя тут могут помочь кодогенераторы). Эта схема работает, только если иерархия классов известна заранее (стандартный C++ RTTI такого не требует).

Всего известно три главных аргумента "против RTTI":
🅱️ Занимает память в бинарнике - очень сомнительный аргумент. RTTI не требует столько памяти, чтобы это стало заметно, по крайней мере в 2023 году.
🅱️ Медленно работает - хороший аргумент, если dynamic_cast<> является узким местом в программе. Но это должна быть специфическая программа, как поиск паттернов в структурах с большой иерархией классов... (например, компилятор C++)
🅱️ Его использование - ошибка дизайна - неожиданный аргумент, но именно по этой причине RTTI запрещен в Google C++ Style Guide. По ссылке есть описание "почему это плохо". Конечно, из каждого правила есть исключение.

BY C++95


Share with your friend now:
tgoop.com/cxx95/94

View MORE
Open in Telegram


Telegram News

Date: |

Ng, who had pleaded not guilty to all charges, had been detained for more than 20 months. His channel was said to have contained around 120 messages and photos that incited others to vandalise pro-government shops and commit criminal damage targeting police stations. 4How to customize a Telegram channel? The visual aspect of channels is very critical. In fact, design is the first thing that a potential subscriber pays attention to, even though unconsciously. 2How to set up a Telegram channel? (A step-by-step tutorial) Matt Hussey, editorial director of NEAR Protocol (and former editor-in-chief of Decrypt) responded to the news of the Telegram group with “#meIRL.”
from us


Telegram C++95
FROM American