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





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

Что бы вы ни выбрали, в нем, вероятно, будут ужасные макросы, сложный для отладки код или странные шаги сборки. Я видел, как одна система автоматически генерирует код сериализации из файла PDB DevStudio.
А если серьезно, то для небольших проектов будет проще написать функции сохранения / загрузки (или использовать операторы потоковой передачи). Фактически, это может быть справедливо и для больших проектов - очевидно, что происходит, и обычно вам все равно придется изменить код, если структура изменится.
+1: за фото;) шучу. Я согласен с выводом. Используйте сериализаторы ручной работы или другой язык :)
В надписи вагон опечатка, должно быть l337!
Вы можете взглянуть на два инструмента ниже. Я никогда не использовал ни один из них, поэтому не могу сказать, насколько они практичны.
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++ 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++ кажется слишком старым.
Я смотрел на эти вещи довольно долго, но они, как правило, очень жесткие. Они могут помешать вам использовать наследование или иметь странные конструкторы и т. д. И т. Д. В конце концов, они стали слишком обременительной, а не удобной.
Этот подход для раскрытия членов, который я сейчас использую, довольно легкий и позволяет вам исследовать класс для сериализации или, например, установки всех полей с именем «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 << " ";
}
}
Хотя мне это нравится, следует отметить, что это не общее решение - например, он прерывается, как только фактический статический тип не известен.
Это хороший подход. Однажды я сделал препроцессор, который генерирует для вас шаблоны функций visit(). А затем несколько функторов для сериализации и десериализации JSON, двоичного кода, текста и т. д. Никаких уродливых макросов. groups.google.com/d/msg/comp.lang.c++/Ila1Tn09mm4/nJVxl3SzpF UJ
Есть новый проект, обеспечивающий отражение на C++ с использованием совершенно другого подхода: ЛАГЕРЬ. https://github.com/tegesoft/camp
CAMP не использует прекомпилятор, классы / свойства / функции / ... объявляются вручную с использованием синтаксиса, аналогичного boost.python или luabind. Конечно, люди могут использовать прекомпилятор, такой как gccxml или open-C++, для генерации этого объявления, если они предпочитают.
Он основан только на чистом C++ и заголовках boost, и благодаря мощности метапрограммирования шаблонов он поддерживает любые виды связываемых сущностей (например, наследование и странные конструкторы не являются проблемой).
Распространяется по лицензии MIT (ранее LGPL).
Это было разветвлено и продолжил, как обдумывать
Посмотрел и на это некоторое время. Текущее самое простое решение - BOOST_FUSION_ADAPT_STRUCT. Практически, когда у вас есть библиотека / заголовок, вам нужно только добавить поля структуры в макрос BOOST_FUSION_ADAPT_STRUCT () как последний сегмент кода показывает. Да, у него есть ограничения, о которых упоминали многие другие люди. И он не поддерживает слушателей напрямую.
Другие многообещающие решения, на которые я обратил внимание:
c2ph / pstruct для сброса метаинформации из вывода gcc -gstabs, который менее навязчив, но требует дополнительной работы, хотя он отлично работал у меня.Что касается подхода boost / __ cxa, как только вы выясните все мелкие детали, добавление / изменение структур или полей станет простым в обслуживании. в настоящее время мы используем его для создания слоя привязки настраиваемых типов поверх dbus, для сериализации API и скрытия деталей транспорта / RPC для подсистемы обслуживания управляемых объектов.
Разрешает ли это / отражение /? Я вижу, как это адаптирует структуру для моделирования концепции последовательности в Boost MPL / Fusion, чтобы вы могли перебирать ее поля. Однако получение имен полей или использование имен для доступа к полям не может быть и речи, IIRC. Я даже не говорю о самом типе структуры
@sehe: Как видите, типы полей печатаются __cxa_demangle (typeid (t) .name ()). Эту же функцию можно применить к декодеру структуры и декодеру массива для печати всех типов структур и типов массивов, включая самый верхний уровень. Если вы думаете, что java vm хранит список всех классов / объектов во внутреннем двоичном списке, метаданные, которые выводятся в этом примере, находятся примерно на этом уровне. Из этой низкоуровневой информации (плюс информация об адресе времени выполнения) вам необходимо написать код для доступа к полям (по именам в формате string или char []). Это будет вторая половина всей картины отражения.
Ах. Итак, самой важной части ответа на самом деле нет. Хммм, это было удивительно. В любом случае, я +1 для c2ph/pstruct. Oldschool, но на самом деле будет работать в большинстве мест. __cxa * не совсем переносимый. И ADAPT_STRUCT не очень актуален, с ним легко работать, и его нелегко автоматизировать. Если вы используете макросы, вы также можете использовать макросы полностью (и не зависеть от Boost или GCC ABI)
На самом деле, самая важная часть для меня - это наименьшие затраты времени выполнения и наименее навязчивый процесс. c2ph / pstruct не очень портативен, как может показаться. Мне пришлось потратить большие усилия, чтобы исправить pstruct для конкретного дампа gcc stabs. После сброса информации о типе и получения информации об адресе из встроенного двоичного файла в среду выполнения необходимо встроить только интерфейс доступа к памяти. Все остальное можно сделать из коробки (я занимаюсь встроенным программированием и использую отражение в основном для тестирования). Таким образом, ADAPT_STRUCT - самое простое решение, которое я могу найти.
Просто перефразируйте последний комментарий Реда: вы делаете два раунда. Первый этап компиляции / запуска на хост-машине с использованием __cxa * / boost для сброса метаинформации. Второй раунд для создания метаинформации в указанном вами формате в цели. Тогда в целевой сборке нет зависимости от boost или g ++.
Набор инструментов для автоматического самоанализа / рефлексии. Используйте мета-компилятор, такой как Qt, и добавляйте метаинформацию непосредственно в объектные файлы. Интуитивно простой в использовании. Никаких внешних зависимостей. Даже позволяет автоматически отображать std :: string, а затем использовать его в скриптах. Посетите я не знаю
Ссылка говорит: «Вам нужно разрешение», очевидно, для этого сайта установлен частный доступ.
Если мое приложение уже не использует Qt, я создаю операторы потоковой передачи для каждого из моих классов, которые необходимо сохранить.