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



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: |

During a meeting with the president of the Supreme Electoral Court (TSE) on June 6, Telegram's Vice President Ilya Perekopsky announced the initiatives. According to the executive, Brazil is the first country in the world where Telegram is introducing the features, which could be expanded to other countries facing threats to democracy through the dissemination of false content. While the character limit is 255, try to fit into 200 characters. This way, users will be able to take in your text fast and efficiently. Reveal the essence of your channel and provide contact information. For example, you can add a bot name, link to your pricing plans, etc. It’s yet another bloodbath on Satoshi Street. As of press time, Bitcoin (BTC) and the broader cryptocurrency market have corrected another 10 percent amid a massive sell-off. Ethereum (EHT) is down a staggering 15 percent moving close to $1,000, down more than 42 percent on the weekly chart. 2How to set up a Telegram channel? (A step-by-step tutorial) Hashtags are a fast way to find the correct information on social media. To put your content out there, be sure to add hashtags to each post. We have two intelligent tips to give you:
from us


Telegram C++95
FROM American