Рефлексия



Вам когда-нибудь хотелось получить значение enum'а, который имеет имя, соответствующее определенной строке? Или например во время выполнения на основе данных конфига выбрать подходящий класс для обработки? Или вызвать метод класса с помощью строки, содержащей его имя? Да все это в плюсах можно сделать, но какой ценой. Нужны эти нагромождения условных конструкций, которые смотрятся просто ужасно и от которых глаза вытекают из орбит. Почему нельзя сделать так, чтобы существовала какая-то структура, типа словаря, к которому можно обращаться в рантайме и выбирать произвольный тип, из которого я хочу создать объект?



Ответ прост. Можно. Но не в плюсах)



Эта фича называется рефлексией. То есть это способность программы получать информацию о своей структуре и изменять ее. Простым языком: она позволяет вам вызывать методы объектов, создавать новые объекты, модифицировать их, даже не зная имён интерфейсов, полей, методов во время компиляции. Из-за такой природы рефлексии её труднее реализовать в статически типизированных языках, поскольку ошибки типизации должны быть отловлены во время компиляции, а не исполнения программы, чтобы все работало корректно. И хоть это возможно для байт-код языков, типа жабы и Си за решеткой, но для плюсов это сделать очень трудно. Вы конечно сами где-нибудь можете набросать какой-то код, который будет имитировать рефлексию, но полноценного стандартного решения рантайм рефлексии мы не получить не можем и на это есть несколько причин.



1️⃣ Язык C++ имеет совместимость с языком C и является его логическим приемником. Поэтому он стремится быть эффективным и близким к машинному коду. Полноценная рефлексия встроенная в язык требует дополнительные значительные вычислительные и ресурсные затраты, что может не соответствовать целям C++ для высокой производительности и низкого уровня абстракции. Как говорится, не плати за то, чем не пользуешься(слоган эмбеддед разработчиков по жизни).



2️⃣ Сюрприз: эффективность кода. Компиляторы с++ знамениты тем, что издеваются над нашим кодом во всех непристойных позициях и выдают самый эффективный машинный код. Они могут разворачивать циклы, встраивать функции и даже целые классы. Это все нужно для максимальной скорости и работает только за счет того, что все известно на момент компиляции. Что позволяет избегать накладных расходов и предоставлять предсказуемое поведение(не всегда). А рефлексия может нарушить эту предсказуемость, а значит и производительность.



Тем не менее плюсы медленно, но верно продвигаются в расширении рефлексивной функциональности. Мало того, что шаблонная магия позволяет из коробки делать очень многие вещи, так и в современных стандартах появляются такие штуки, как std::any, std::experimental::source_location и тд. Вряд ли когда-нибудь завезут что-то стандартное, подходящее всем и для любых целей, если за 40 лет этого так и не случилось ни с одной библиотекой или модулем. Но тенденция явно позитивная. А в пропоузале к С++26 есть даже целый раздел, посвященный статической рефлексии. Так что per aspera ad astra.



Stay optimistic. Stay cool.



#howitworks #hardcore