Библиотеки атрибутов и отражений для C++?

Большинство зрелых проектов C++, похоже, имеют собственный система отражений и атрибутов, то есть для определения атрибутов, к которым можно получить доступ по строке и которые автоматически сериализуемы. По крайней мере, многие проекты C++, в которых я участвовал, казались изобретать велосипед.

Знаете ли вы какой-либо хорошие библиотеки с открытым исходным кодом для C++, который поддерживает контейнеры отражения и атрибутов, в частности:

  • Определение RTTI и атрибутов с помощью макросов
  • Доступ к RTTI и атрибутам через код
  • Автоматическая сериализация атрибутов
  • Прослушивание изменений атрибутов (например, OnValueChanged)
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
17
0
9 098
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Не общий, но QT поддерживает это через мета-компилятор и является GPL. Из разговоров с людьми QT я понял, что это невозможно с чистым C++, отсюда и необходимость в moc.

Это печально известная слабость языка C++ в целом, потому что вещи, которые необходимо стандартизировать, чтобы сделать реализации отражения переносимыми и полезными, не являются стандартными. На ум приходят соглашения о вызовах, макеты объектов и изменение символов, но есть и другие.

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

Вот что вы получаете, когда C++ встречает Reflection:

C++ meets Reflection

Что бы вы ни выбрали, в нем, вероятно, будут ужасные макросы, сложный для отладки код или странные шаги сборки. Я видел, как одна система автоматически генерирует код сериализации из файла PDB DevStudio.

А если серьезно, то для небольших проектов будет проще написать функции сохранения / загрузки (или использовать операторы потоковой передачи). Фактически, это может быть справедливо и для больших проектов - очевидно, что происходит, и обычно вам все равно придется изменить код, если структура изменится.

Если мое приложение уже не использует Qt, я создаю операторы потоковой передачи для каждого из моих классов, которые необходимо сохранить.

Branan 18.09.2008 03:17

+1: за фото;) шучу. Я согласен с выводом. Используйте сериализаторы ручной работы или другой язык :)

neuro 15.06.2010 12:25

В надписи вагон опечатка, должно быть l337!

sehe 06.09.2012 13:29
Ответ принят как подходящий

Вы можете взглянуть на два инструмента ниже. Я никогда не использовал ни один из них, поэтому не могу сказать, насколько они практичны.

XRTTI:

Xrtti is a tool and accompanying C++ library which extends the standard runtime type system of C++ to provide a much richer set of reflection information about classes and methods to manipulate these classes and their members.

OpenC++:

OpenC++ is C++ frontend library (lexer+parser+DOM/MOP) and source-to-source translator. OpenC++ enables development of C++ language tools, extensions, domain specific compiler optimizations and runtime metaobject protocols.

У XRTTI все еще есть обновленная версия для поздних дистрибутивов Linux. OpenC++ кажется слишком старым.

minghua 06.09.2012 12:00

Я смотрел на эти вещи довольно долго, но они, как правило, очень жесткие. Они могут помешать вам использовать наследование или иметь странные конструкторы и т. д. И т. Д. В конце концов, они стали слишком обременительной, а не удобной.

Этот подход для раскрытия членов, который я сейчас использую, довольно легкий и позволяет вам исследовать класс для сериализации или, например, установки всех полей с именем «x» на 0. Он также определяется статически, поэтому работает очень-очень быстро. Никаких слоев кода библиотеки или генерации кода, чтобы беспокоиться о том, чтобы вмешиваться в процесс сборки. Он обобщается на иерархии вложенных типов.

Установите в свой редактор несколько макросов, чтобы автоматизировать написание некоторых из этих вещей.

struct point
{
     int x;
     int y;

     // add this to your classes
     template <typename Visitor>
     void visit(Visitor v)
     {
         v->visit(x, "x"); 
         v->visit(y, "y");
     }
};


/** Outputs any type to standard output in key=value format */
struct stdout_visitor
{
     template <typename T>
     void visit(const T& rhs)
     {
         rhs.visit(this);
     }

     template <typename Scalar>
     void visit (const Scalar& s, const char* name)
     {
          std::cout << name << " = " << s << " ";
     }
}

Хотя мне это нравится, следует отметить, что это не общее решение - например, он прерывается, как только фактический статический тип не известен.

Georg Fritzsche 21.03.2010 15:50

Это хороший подход. Однажды я сделал препроцессор, который генерирует для вас шаблоны функций visit(). А затем несколько функторов для сериализации и десериализации JSON, двоичного кода, текста и т. д. Никаких уродливых макросов. groups.google.com/d/msg/comp.lang.c++/Ila1Tn09mm4/nJVxl3SzpF‌ UJ

Maxim Egorushkin 06.09.2012 12:25

Есть новый проект, обеспечивающий отражение на C++ с использованием совершенно другого подхода: ЛАГЕРЬ. https://github.com/tegesoft/camp

CAMP не использует прекомпилятор, классы / свойства / функции / ... объявляются вручную с использованием синтаксиса, аналогичного boost.python или luabind. Конечно, люди могут использовать прекомпилятор, такой как gccxml или open-C++, для генерации этого объявления, если они предпочитают.

Он основан только на чистом C++ и заголовках boost, и благодаря мощности метапрограммирования шаблонов он поддерживает любые виды связываемых сущностей (например, наследование и странные конструкторы не являются проблемой).

Распространяется по лицензии MIT (ранее LGPL).

Это было разветвлено и продолжил, как обдумывать

Nick 18.05.2016 21:41

Посмотрел и на это некоторое время. Текущее самое простое решение - BOOST_FUSION_ADAPT_STRUCT. Практически, когда у вас есть библиотека / заголовок, вам нужно только добавить поля структуры в макрос BOOST_FUSION_ADAPT_STRUCT () как последний сегмент кода показывает. Да, у него есть ограничения, о которых упоминали многие другие люди. И он не поддерживает слушателей напрямую.

Другие многообещающие решения, на которые я обратил внимание:

  • CAMP и XRTTI / gccxml, однако оба кажутся препятствием для внедрения зависимости внешних инструментов в ваш проект.
  • Несколько лет назад я использовал perl c2ph / pstruct для сброса метаинформации из вывода gcc -gstabs, который менее навязчив, но требует дополнительной работы, хотя он отлично работал у меня.

Что касается подхода boost / __ cxa, как только вы выясните все мелкие детали, добавление / изменение структур или полей станет простым в обслуживании. в настоящее время мы используем его для создания слоя привязки настраиваемых типов поверх dbus, для сериализации API и скрытия деталей транспорта / RPC для подсистемы обслуживания управляемых объектов.

Разрешает ли это / отражение /? Я вижу, как это адаптирует структуру для моделирования концепции последовательности в Boost MPL / Fusion, чтобы вы могли перебирать ее поля. Однако получение имен полей или использование имен для доступа к полям не может быть и речи, IIRC. Я даже не говорю о самом типе структуры

sehe 06.09.2012 13:37

@sehe: Как видите, типы полей печатаются __cxa_demangle (typeid (t) .name ()). Эту же функцию можно применить к декодеру структуры и декодеру массива для печати всех типов структур и типов массивов, включая самый верхний уровень. Если вы думаете, что java vm хранит список всех классов / объектов во внутреннем двоичном списке, метаданные, которые выводятся в этом примере, находятся примерно на этом уровне. Из этой низкоуровневой информации (плюс информация об адресе времени выполнения) вам необходимо написать код для доступа к полям (по именам в формате string или char []). Это будет вторая половина всей картины отражения.

minghua 07.09.2012 11:13

Ах. Итак, самой важной части ответа на самом деле нет. Хммм, это было удивительно. В любом случае, я +1 для c2ph/pstruct. Oldschool, но на самом деле будет работать в большинстве мест. __cxa * не совсем переносимый. И ADAPT_STRUCT не очень актуален, с ним легко работать, и его нелегко автоматизировать. Если вы используете макросы, вы также можете использовать макросы полностью (и не зависеть от Boost или GCC ABI)

sehe 07.09.2012 11:23

На самом деле, самая важная часть для меня - это наименьшие затраты времени выполнения и наименее навязчивый процесс. c2ph / pstruct не очень портативен, как может показаться. Мне пришлось потратить большие усилия, чтобы исправить pstruct для конкретного дампа gcc stabs. После сброса информации о типе и получения информации об адресе из встроенного двоичного файла в среду выполнения необходимо встроить только интерфейс доступа к памяти. Все остальное можно сделать из коробки (я занимаюсь встроенным программированием и использую отражение в основном для тестирования). Таким образом, ADAPT_STRUCT - самое простое решение, которое я могу найти.

minghua 07.09.2012 11:45

Просто перефразируйте последний комментарий Реда: вы делаете два раунда. Первый этап компиляции / запуска на хост-машине с использованием __cxa * / boost для сброса метаинформации. Второй раунд для создания метаинформации в указанном вами формате в цели. Тогда в целевой сборке нет зависимости от boost или g ++.

minghua 31.12.2014 20:26

Набор инструментов для автоматического самоанализа / рефлексии. Используйте мета-компилятор, такой как Qt, и добавляйте метаинформацию непосредственно в объектные файлы. Интуитивно простой в использовании. Никаких внешних зависимостей. Даже позволяет автоматически отображать std :: string, а затем использовать его в скриптах. Посетите я не знаю

Ссылка говорит: «Вам нужно разрешение», очевидно, для этого сайта установлен частный доступ.

Andreas Haferburg 10.05.2018 21:34

Другие вопросы по теме