Ищу единомышленников для open source проекта на С++

Всем привет! Такое дело... Есть С++ библиотека, но отчаянно не хватает людей, с которыми можно было бы до хрипоты спорить о том, что плохого в добавлении С++ рантайма и каких ещё ништяков добавить в нашу библиотечку!

Суть библиотеки в двух словах — добавить возможность рефлексии «on demand» для плюсов. Представьте только себе: возможность использовать поля классов по их строковым именам в рантайм! Какие это возможности открывает... Уже сейчас библиотека умеет создавать object inspector-ы на базе Qt для объектов! Прям как в Unity, если кто имел дело, когда объект выбираешь и его редактировать можно (кстати, библиотека делается с прицелом как раз на геймдев)!

Проект имеет прозрачную архитектуру, есть некоторая проектная документация и UML для классов.

Присоединяйтесь, станете сооснователем! Пока ещё есть возможность вложить свою лепту в развитие библиотеки, которая перевернёт мир работы с GUI для С++!

Чуть подробнее про проект:
docs.google.com/...​hwh1gdJKPnpPlCsVlhUk/edit

(ОБНОВЛЕНО)
Добавлю, пожалуй, контакты и сюда:

Почта: [email protected]
VK: vk.com/id192414625
Facebook: www.facebook.com/...​emenyakin/100011274901930

Linked in: ua.linkedin.com/...​адимир-семенякин-88a3217b
Habrahabr: habrahabr.ru/users/semenyakinvs

Пишите туда, куда вам удобно... Ну, и в личку на dou писать можете, ага.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Ну, если интересно — можете почитать комментарии к этому топику. Там уже много обсуждения, не буду повторять всё.

А почему в С++ reflection считается плохим тоном? В Java некоторые фреймворки активно используют reflection, например Spring and Hibernate.

Конечно, кодить с прицелом на reflection считается плохим тоном из-за нарушения инкапсуляции, но иногда без неё не обойтись.

Плюсовики помешаны на опимизации, и готовы иногда городить чёртов ад в прикладном коде ради нескольких тактов процессора. Бывает это нормально и уместно, но иногда доходит до патологии

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

О, более конструктивные посты... Спасибо! Почитав отзывы людей (вы подвели итог эти отзывам), я тоже начинаю подумывать о кодогенерации... Но кодогенерация тоже требует некоторого кода — минимум, для хранения информации о рефлексии. Без библиотек, увы, не обойтись в любом случае... Вообще, сейчас мысль такая, что кодогенерация будет использоваться в качестве дополнительной возможности, которая позволит за пользователя выполнить явную передачу информации о классах.

Если уж заговорили по поводу кодогенерации — не подскажете какой приём лучше всего использовать для кодогенерации? Была идея взять clang и механизм generalized attributes из C++11 (для добавления дополнительной информации об элементах классов), но потом выяснилось, что нельзя делать user defined атрибуты... Вот думаю — может, использовать подход аля Qt MOC, с пустыми макросами и отлавливать следующие за макросами элементы языка... Так вообще можно в рамках clang, брать именно следующий элемент за макросом?

Пиши на Lisp’е, занимайся настоящей кодогенерацией, %username%!

Увы, для некоторых проектов важен перформанс.

Как показывает опыт, без нее _всегда_ можно обойтись. Поэтому многие против нее.
Чаще всего вместо рефлексии можно просто статически генерировать код.
Многие «задачи» типа ORM вообще бессмыслены — толку от этих всех фреймворков ноль, писать выемку из БД не так уж сложно.

Вот тут Oleksiy Protas уже приводил статью с предложением дизайна-"убийцы" ORM. Комменты к статье, на мой взгляд, достаточно неплохо показывают почему идеи автора по крайней мере не очень хороши (хотя бы в смысле тонн копи-пасты). Может, вы знаете какие-нибудь статьи, в которых давалась бы достойная альтернатива ORM?

(Через пять минут): Глянул на хабре статеек. Вот, например. Ещё одна попытка сделать убийцу ORM. Рейтинг перевода (тобишь это не автор статьи так отхватил, а автор статьи за перевод статьи) −1. Как я писал уже тут, сам я не очень глубоко с концепцией ORM разбирался, но там комментят люди с хорошим опытом работы, вроде. И я понимаю их негодование. ORM — это не про то, чтобы специально злобно делать запросы к БД неоптимальными и специально строить коллстеки на сотни вызовов (хотя это необходимое зло). ORM — это про то, чтобы сделать ваш прикладной код чище, избавив его от мусорной копи-пасты для однотипных запросов к БД. Не нравится как ведёт себя ORM в некоторых местах — используйте там какие-нибудь тонкие оптимизации с прямыми запросами к БД.

И, на мой взгляд, такой же подход должен быть к С++. Есть ботлнек где-то в коде, который сжирает 30% ресурсов? Нужно конкретно эту часть кода, оптимайзить. Но, на мой взгляд, это не повод оптимизировать вплоть до отдельных тактов прям весь остальной код — особенно если при этом он превращается в трудночитаемый и трудноотладиваемый кроссворд из шаблонов и макросов, как это бывает при использовании того же boost. Именно за подобную практику люди не любят плюсы и именно она, как мне кажется, не в последнюю очередь не даёт этому горячо любимому мною языку стать по-настоящему широко используемым.

Не надо ни на что заменять ORM. Просто не надо этого слоя. Если данные в БД — пусть там и будут, работайте с БД. Если они на вебсервесе — общайтесь с вебсервисом. Зачем кривая и тормозная прослойка?

Зачем кривая и тормозная прослойка

Потому, что часто предпочтительной метрикой при разработке выступает скорость написания проекта и простота кода в смысле осознания его новыми людьми, а отнюдь не эффективность... И опять замечу что говорю как человек, знакомый с ORM весьма косвенно, со своего двухмесячного опыта изучения на курсах Java EE и со слов знакомых.

Бредовая метрика. И API, скажем, SQLite намного проще и понятнее чем дескрипторы и прочая глупость Hibernate.

Бредовая метрика

Отличная метрика. Делает разработку дешевле.

чем дескрипторы и прочая глупость Hibernate

Вот тут ничего не могу сказать. Работал с Hibernate на уровне добавления аннотаций в классы для их привязки к ORM и элементарных запросов... Кстати, по каким-то причинам у меня там сломался ORM, и финальное задание я делал на чистом JDBC. Могу сказать прямо — там был вагон копи-пасты и я жалел под конец, что не потратил время на нормальную настройку ORM.

(чуть позже) Глянул примеры. SQLite vs Hibernate. В данных примерах SQLite выглядит действительно намного проще... Но что случится когда классов станет хотя бы десяток? Ну и, также, в примере SQLite нет никакого кода для, собственно, маппинга значений в плюсовые типы, там их только выводят на экран. Hibernate же это всё умеет сразу. Можно сказать, конечно, что то плюсы, а то — джава... Хорошо, вот пример для Java. Добавляется тайпкаст... Для плюсов такое тоже, есть, наверно, через шаблоны, но, тем не менее, в рамках реального кода всё равно придётся заполнять полученными из таблицы значениями какие-нибудь объекты — потому, что программа оперирует объектами, а не отдельными значениями.

Еще, reflection многие оптимизации не дает делать компилятору и линкеру. Требует толстый рантайм (многие проекты — например Хром — компилируются без RTTI, даже тип объекта нельзя узнать в рантайме). Reflection поощряет плохие практики (ORM, автоматически сгенеренные UI, т.д.)

Почему рефлексия не даёт делать оптимизации? Если лень долго рассказывать — может, ссылку какую-нибудь дадите по поводу?

Кстати, речь идёт не о копировании RTTI — знаю, штука не очень, её на моём последнем проекте тоже отключали — а о добавлении рефлексии явно через код (в обход RTTI) лишь для некоторых классов (и только для них). Добавление рефлексии только к тем классам, использование рефлексии для которых позволит облегчить работу с проектом в целом...

П.С.: Я, кстати, до конца так и не понял до сих — почему автоматически сгенерированное GUI это плохая практика (про ORM вопрос задаю в соответствующем вашем комменатрии)? А как ещё делать, если мы пишем, например, редактор для игры и объекты игровых объектов десятки параметров, перечень которых может ещё и менять в течение жизни проекта. Что, вручную создавать GUI-редактор (и, что ещё хуже, поддерживать его) для каждого-каждого класса, которых в игре могут быть около сотни? Мне кажется, тогда 30% времени программисту придётся, как говорят, «формошлёперством» заниматься.

Оптимизации — рефлексия не позволяет инлайнить методы, удалять неиспользуемый код, делать некоторые предположения (например, о том как часто какое-то поле используется) и т.д.

Генеренный UI — всегда г-но, недружелюбное для пользователю. GUI редактор работает с моделью а не с реальными объектами. Т.е. ему рефлексия вообще нафиг не нужна — он не делает button.getClass().getField("text").setValue("Click here") а button.setField("name«, «Click here»). По скти — hashmap, со всякими листнерами и т.д. Живые объекты очень стремне в редакторе дернуть — кто-то кривой компонент написал — редактор падает.

Хм. Мне кажется, или мы разные вещи понимаем под рефлексией.

рефлексия не позволяет инлайнить методы, удалять неиспользуемый код, делать некоторые предположения

Рефлексия строится над объектами, никак не влазя в их внутреннюю структуру — для примера можете тот же rttr, который я упоминал уже глянуть. Поэтому я не понимаю почему нельзя инлайнить методы или нельзя удалять неиспользуемый код... По поводу предположений — вы имеете в виду branch prediction? Если так — исходя из сказанного выше тоже не особо понимаю причём здесь рефлексия.

GUI редактор работает с моделью а не с реальными объектами

Да, это во многом правда. Редактор должен жить над объектами и связываться не с ними, а с их API. Поэтому для пользовательских приложений использование рефлексии, вероятно, не подойдёт... Однако для внутренних редакторов для тех же игровых проектов, которые живут в бурной среде, подчинённой геймдизайнерам (что нормально — геймдизайнеры имеют право и должны активно прототипировать фичи), по моему опыту работы набор свойств объектов может меняться достаточно динамично. При этом поддерживать полноценное ручное MVC — запаришься.

Живые объекты очень стремне в редакторе дернуть — кто-то кривой компонент написал — редактор падает

Вот с этим соглашусь. Если байндить рефлексию напрямую к значениям полей (аки дебаггер) — могут быть проблемы, связанные с игнорированием при таком подходе логики в API объекта (акссесоров). На мой взгляд, в RTTR эта тема достаточно изящно решена за счёт байндинга не значений напрямую, а аксессоров (например: property("data", &MyStruct::data) — передача readonly проперти). Для свойств, изменения которых требуют обновления каких-нибудь состояний модели, над которой живёт GUI, можно сделать debug-only сеттер и через него обновлять нужные состояния.

Что, вручную создавать GUI-редактор (и, что ещё хуже, поддерживать его) для каждого-каждого класса, которых в игре могут быть около сотни?
Могу подсказать решение этой проблемы, если вам интересно. Не нужно вообще никаких редакторов, достаточно просто иметь возможность изменять скрипты в рантайме. А это сделать несложно. Тогда вы будете не только менять константы на лету, но и алгоритмы.

Ну, программистам, может, и не нужен. Но гейм-дизайнерам намного приятнее с графическим интерфейсом иметь дело — это раз (объектам при создании уровня нужно координаты выставлять — что, тоже через lua bind гонять данные будете, да?)... Ну и, конечно, всю игру на lua вы не сделаете. Есть часть, которая живёт в плюсах и которая должна бегать быстро, без привязки к скриптам с одной стороны, и которую дизайнерам хотелось бы редактировать — с другой.

П.С.: Возможно, я не совсем точно понял вашу идею. Если так — извиняюсь, можете описать точнее.

Дизайнеры работают в основном под 3DS MAX и в фотошопе, и под это затачивается разработка. Ну разве что только в высокобюджетных проектах есть отдельно взятые дизайнеры уровней, которые сидят в специально для них сделанных редакторах уровней, типа Far Cry, и прочие люди с узким кругом задач.

Общая схема такова. Есть небольшая надстройка над движком, которая поставляет хостовый API для скриптов. Если архитектура организована правильно, то хостовый API на C++ выполняет только низкоуровневые нагруженные операции, а вся логика крутится в скриптах. Для всех объектов создаётся репрезентация в Lua-скриптах, где определяются все свойства, логика поведения и вобщем весь геймплей. Например, создаётся userdata-объект, биндится загруженным из ресурсов мешем, инициализируется согласно какой-то логики нужными значениями, и дальше скрипты как-то крутят его в общей сцене. Скрипты можно компилировать и выполнять в рантайме, и соответственно прямо на лету можно редактировать свойства и логику.

Большое спасибо что так подробно рассказали! Действительно интересно! Если не секрет — что за компания? На linked in чего-то не показывается.

Если возможно, я ещё несколько вопросов задать хотел бы... Не знаю, вероятно, могут NDA нарушать, поэтому если нельзя или не хочется отвечать — не отвечайте, но если всё-таки выйдет ответить — есть шанс взаимно обогатиться опытом. Вопросы задаю в порядке уменьшения степени их отношения к теме рефлексии.

Для всех объектов создаётся репрезентация в Lua-скриптах, где определяются все свойства, логика поведения и вобщем весь геймплей

Уровни тоже вручную через lua набиваются? То есть вообще нет никакого GUI-редактора? А насколько много свойств у ваших объектов бывает?

Например, создаётся userdata-объект, биндится загруженным из ресурсов мешем, инициализируется согласно какой-то логики нужными значениями, и дальше скрипты как-то крутят его в общей сцене

То есть все свойства в основном живут и изменяются в луа, а рендер и (возможно) физика обитает в плюсовом коде и они дёргаются из луа?.. К чему спрашиваю... Рендер, как нечто, что может не влиять на состояние логики игры (хотя и это не всегда правда) ещё можно рисовать с отставание в один кадр и юзер этого почти не заметит. Но физика вызывает изменении состояния игровых объектов и это касается непосредственно логики, которая живёт в луа и доступна из плюсового кода только через, как я понимаю, медленную bind-связку. Такая схема не будет бить по FPS?.. Хотя... Неужто lua умеет в хорошо оптимизированный код собираться? Вопрос немного оффтоповый выходит, но реально интересно.

Ну разве что только в высокобюджетных проектах есть отдельно взятые дизайнеры уровней

Я думал, что уровни и правила игры геймдизайнеры делают, а ребята, которые в 3DS MAX и в фотошопе работают, называются «артистами» или художниками и/или моделлерами... Или это от расплывчатое разделение, типа как позиция middle-программиста, которая тоже часто не ясно что значит?)

Раньше я работал на soft-Xpansion (бывший Maus software), где главным образом писал код 3D симулятора бильярда, затем перешёл в небольшую команду с разработкой игр для казино. С soft-Xpansion срок NDA истёк, со второй командой не подписывал, поскольку основной разработчик C++, неуместно как-то :)

В проекте «Battle Of Europe» выпущенном в 2006 года от soft-Xpansion скриптование вообще не использовалось, уровни со всеми данными и логикой — написаны на C++. И там проблема даже не в инициализации объектов, как в самом вермешелеобразном коде геймплея. Один из switch с перебором состояний и деревьями условий например занимает порядка 3000 строк. При любом изменении логики состояний, что-то меняется во многих местах такого кода, и это всё надо тестировать. Это одна из причин, почему логику лучше скриптовать.

В проекте бильярда правила игр уже скриптовались, правда уровень абстракции хостового API небольшой. Инициализация «уровня» (комната, стол, кий, шары) делается в скрипте, там же прописаны функции-отклики на события. В дальнейшем, в играх для казино уровень абстракции уже достаточный, чтобы можно было написать полностью новую игру без изменений в коде на С++ (никаких функций-откликов на события и колбэков — нет). Хостовый код и движок конечно при этом постоянно развивается, без привязки к каким-либо данным или логике игр. Если сопоставить трудоёмкость, где-то 80% времени занимает скриптование логики, по сравнению с модификациями движка.

Насчёт рендеринга. В 3D строится граф объектов (мешей, источников света), при графическом рендеринге движок обходит граф, и отрисовывает узлы каждый кадр. Но сначала физический рендер пересчитывает физические параметры, определяет коллизии. Также каждый кадр возобновляется работа ряда Lua-коротинов, которые выполняют какой-то квант работы над каким-то объектом (перемещают, поворачивают), собственно именно в них и крутится вся логика. Стоимость вызова функции хостовой C++ точно такая же, как и стоимость вызова любой стандартной функции. luabind лично я не использую по ряду причин, для связки юзаю модифицированный класс Luna, который лежит где-то на официальном сайте от разработчиков lua. К тому же это больше возможностей, хостовые функции могут например принимать и возвращать переменное число аргументов и разных типов, в зависимости от ситуаций. JIT компилятор использовать идея хорошая, только он не поддерживает спецификацию 5.3. Даже без JIT выдаётся вполне приличный FPS, без вертикальной синхронизации на Core i7 порядка 1200-1800 кадров в сек. Поскольку полигонов немного по современным меркам, видюха значения не имеет. Чтобы свести к минимуму работу скриптов, некоторые операции над объектами выполняются над списком сразу. Ну и естественно, инициализация всего по возможности выносится на период загрузки ресурсов, все ресурсы — кэшируются.

Ух, круто, как вы снова всё расписали! Спасибо!

Battle Of Europe

То есть вот был написан авиасимулятор, и к нему не было даже скриптового редактора?! Как вообще геймдизы жили? Они что, плюсовый код меняли что ли?!

Один из switch с перебором состояний и деревьями условий например занимает порядка 3000 строк

Мммм.... Нет. Трудно что-то говорить по этому поводу. Даже теоретически не представляю каково вам было это поддерживалось. Сурово, однозначно очень сурово...

Инициализация «уровня» (комната, стол, кий, шары) делается в скрипте, там же прописаны функции-отклики на события

Вот в чём дело... Бильярд. Ну, да. Там вряд ли нужны сложные уровни, больший упор на физическом моделировании самой игры... Но описанный вами workflow работы для игры с упором на усложнение игровых правил, боюсь, был бы неудобен для команды. Например, для стратегии, где в рамках сюжетных миссий могут быть тысячи объектов на карте, сотни из которых могут требовать специальной тонкой настройки некоторых из десятков параметров (включая, как я говорил, положение объекта на карте, внешний вид и прочие, требующие взгляда дизайнера на то, как объект при этом на карте выглядит).

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

Да, на тех проектах, с которыми я имел дело, тоже на чистых скриптах многие вещи делались, полезная возможность... Но с возможность для геймдизов редактировать такие объекты через GUI.

Также каждый кадр возобновляется работа ряда Lua-коротинов, которые выполняют какой-то квант работы над каким-то объектом (перемещают, поворачивают), собственно именно в них и крутится вся логика

А какая нужна скриптовая логика для бильярда? Вроде, правила там не особо сложные. Или в игре разные какие-то бильярдные задачки и компания есть и скрипты для них нужны?.. Но всё равно про физику непонятно («перемещают, поворачивают»). Я так понимаю, физические объектики-сферки и так перемещаются в рамках хоста (плюсовой части движка, тобишь)... Зачем ещё скрипты над этим? Они как-то связывают перемещение и отображение графики?.. Впрочем, это уже, наверно, совсем «интимные» для проекта вопросы.

Battle Of Europe писал не я, это проект был до меня. Игра вообще сделана со вкусом, хоть и не выдерживает конкуренции с «ИЛ-2 штурмовик», появившейся позже. Все модели — разработаны в 3ds max, используются в своём формате (для чего написан плагин под max), а весь код в игре полностью на С++. Только интерфейс описывается скриптом, но не исполнительным, а декларативным. Так же как и в бильярде в дальнейшем, поскольку юзается один движок. Уровни программировал тот же разработчик, который писал и остальной код, и помимо уровней там и других задач достаточно.

А какая нужна скриптовая логика для бильярда?
Есть порядка 50 видов бильярдных игр с разными правилами, в симуляторе заложены наиболее распространённые: 8-ка (на американском столе), 9-ка, русский бильярд (русский стол), карамболь (французский стол, без луз), снукер (английский, снукерный стол), и некоторые ещё. Правила игр вполне чёткие, и строго в соответствии им были запрограмированны. Там есть «ядро» геймплея на столе, которое посылает в «оболочку» правил игры события: коллизия между 2 шарами, шара с бортом, с фишкой, попадание в лузу, вылет за борт и т.п. Дальше витиеватая логика решает, как на это реагировать. Также сделана реальная физика бильярдных ударов: можно менять силу удара, точку удара по битку, угол наклона кия, и таким образом, делать боковики, удары накатом, оттяжку. Разве что пихать кием биток нельзя, но это всё равно запрещено правилами. Шары при некоторых ударах могут прыгать, и вылетать за борт. Эргономика управления кием на мой взгляд очень удобная. Ещё в игре предоставляется делать некоторые бильярдные трюки, я подобрал наиболее зрелищные, не связанные с лишними махинациями на столе. Например «бабочка» — когда 6 шаров 1 ударом разлетаются в лузы. Соответственно, рассчитаны позиции, показывается пример (можно замедленной съёмкой) и даётся возможность повторить.
Там есть «ядро» геймплея на столе, которое посылает в «оболочку» правил игры события: коллизия между 2 шарами, шара с бортом, с фишкой, попадание в лузу, вылет за борт и т.п. Дальше витиеватая логика решает, как на это реагировать

Ага... Спасибо, вот, теперь ясно. То есть скрипты живут над какими-то очень высокоуровневыми событиями игры и, там, в зависимости от правил что-то делают. Например, при вылете за поле либо ставится забитый раньше шар обратно на стол (как в русском бильярде), либо противник имеет возможность белый шар где угодно поставить (как в американке), да?

Также сделана реальная физика бильярдных ударов

Ух ты. Про физику звучит мощно... А трение и подкрутка шаров тоже учитывается? Слышал, в бильярде за счёт подкрутки можно чуть ли не «сухие листы» забивать. Правда, или враки?
Физику сами писали или движок какой-нибудь брали?

Да, в американке есть игра с руки, после забития битка в лузу можно играть с произвольной точки на столе, разбивать пирамиду вначале можно с любой точки на половине стола. В снукере есть игра из сектора. Перед ходом в американке, по правилам, нужно указать прицельный шар и лузу. В большинстве игр биток только один (белый обычно), в русском бильярде может быть любой шар. Вылетевший шар не во всех играх возвращается. Можно также играть и без соблюдения правил, не обращая внимания на фолы, принудительного следования правилам там нет. Скриптовать можно не только правила, всю полностью логику можно было бы написать на скрипте, без потери производительности, что в дальнейших проектах и было реализовано.

Трение о полотно и подкрутка движком конечно учитываются. Для рендеринга физики используется движок от newtondynamics с некоторой кустомизацией, разработанный для расчётов физики сплошных твёрдых тел. Если ударить не по центру шара, в любом случае будет подкрутка. Если это удар сбоку (боковик), шар можно подкрутить так, чтоб катился по дуге, и на эту тему в игре есть даже один простой бильярдный фокус, боковик от борта, когда шар ударяет в борт, обходит по дуге другой шар, и забивает в лузу ещё один.

reflection считается плохим тоном из-за нарушения инкапсуляции,
для чого тоді ООП і ООД?

Взагалі рефлекшени активно обговорюються С++ комітетом, тому це вельми serious business і скоріше питання лише коли. Загугліть он C++ 17 reflection.

Так, здається, тут вже кидали з проводу рефлексії посилання... Насправді, слушна думка врахувати можливість зміни механізма саме для роботи з рефлексією, щоб у разі введеня її у стандарт, легко добавити її у проект.

Из приведённого документа:
Во-первых, вы смешиваете две совершенные разные по уровню задачи — реализацию reflection API для C++. Первая из них: серьезно и никак не связано сдалее описанной прикладной задачей, и уж никак не должно быть загрязнено особенностями какого-то гуя, где имплементация будет использоваться. Можно интересоваться текущим состоянием идей по этому поводу у «комитетчиков», которые стоят собственно за C++: root.cern.ch/blog/status-reflection-c
Во-вторых, определитесь уже, чего вы добиться хотите — решить свою насущную проблему с сериализацией/десериализацией или потрудиться над более более абстрактной вещью.
В-третьих, «напишите и я дам доступ в репу» — серьезно? Это или OSS и pull requests are welcome, или сидите в своей песочнице и дальше.
В-четвёртых, only english.

Во-первых

В библиотеке есть три слоя API. Один из них — это интерфейс для абстрактного связывания состояния объекта с чем бы то ни было. Этим чем-то может выступать как сериализатор во что угодно, так и механизм, организующий привязку к объекту. Как раз механизм, для привязки рефлексии к объектам — это второй слой. Он не имеет отношение к гуи, его можно использовать просто для осмотра состояния объекта в рантайм — вплоть до значения каждого отдельного поля. Ну, и третий слой — это гуи, которое автоматически генерируется путём перебора информации о полях из второго слоя... По поводу комитета — я читал некоторые обсуждения по поводу. На мой взгляд, стоит делать возможность включения рефлексии опционально, для некоторых классов. Рефлексия для любой распоследней структурки на два поля — это плохо. В библиотеке стараюсь придерживаться такого подхода.

Во-вторых

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

В-третьих

Ну, я пока в open source не готовы выкладывать код. Он местами написан грязно и не везде как следует структурирован. Я уже показывал проект людям по запросу, в общем и целом ко мне уже человек шесть постучались по поводу, причём один... точнее, одна из них — весьма толковый С++ программист, так что... Опубликуем когда проект будет готов к этому.

В-четвёртых

Не понял. Зачем onle english для русскопонимающей аудитории dou.ua? Чтобы выпендриться?

П.С.: В целом — большое спасибо за комментарий. Один из первых, в котором есть конструктивная критика.

>

В библиотеке есть три слоя API...
Это плохо. Поймите, что не стоит делать всё что только придёт в голову в одной библиотеке. Просто потому что это сложно, это увеличивает цену понимания/использования/доработки. Что проще взять и начать использовать — uclibc или glibc? (пример плохой, но я с ходу не вспомню что-то более подходящее, потому как не пишу на неуправляемых языках).

>

Решить абстрактную проблему...
Измените (разделите) goal проекта и к вам, возможно, придут люди с более абстрактными подходами к проблеме, со знанием языка вообще.

Ну и остальное — чтобы облегчить жизнь контрибьюторам. Если с доу их пришло 6, то с reddit/r/c++ - может придти хотя бы посмотреть/обсудить те же 60.
Речь идёт не о языке поста, а о языке документа.

Что проще взять и начать использовать — uclibc или glibc

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

Сейчас пользователю достаточно унаследовать интерфейс для своих классов, описать метод bind(IBinding &outBinding) в своём классе и передать в рамках этого метода информацию о полях. Как-то так:

virtual void bind(IBinding &outBinding) {
outBinding.bindInt("Integer field", _intField);
outBinding.bindObject("Object field", _innerObject);
//etc.
}

После в качестве IBinding возможно подсовывать любые реализации — от сериализатора, до класса, генерирующего слой рефлексии.

Чтобы сохранить объект, например, в файл, пользователю достаточно сделать что-то вроде:

UserObject theObject;
FileSerializer theSerializer("save.xml«);
theObject.bind(theSerializer);
theSerializer.save();

Чтобы собрать нужную для рефлексии информацию, можно использовать следующий код:

UserObject theObject;
FieldBinder theBinder;
theObject.bind(theBinder);
// Print fields info
for(IField *theField : theBinder.fields()) {
std::cout << theField->name() << «\t» << theField->type() << std::endl;
}

Чтобы использовать информацию, собранную о полях объекта, для GUI, можно использовать следующий код:

// Используем тут всё тот же «FieldBinder theBinder»
QtObejctInspector theInspector(theBinder);
mainWindow.setCentralWidget(&theInspector.view());

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

Измените (разделите) goal проекта и к вам, возможно, придут люди с более абстрактными подходами к проблеме, со знанием языка вообще.

Ну, выделить по библиотеке под каждой слой... Да, идея интересная. Подумаю над этим.

Речь идёт не о языке поста, а о языке документа.

Когда на reddit писать буду — переведу, конечно. Просто, мне кажется, это своего рода уважение к аудитории — писать на языке, который ей удобен. (*шёпотом* я ещё действительно немного плаваю в английском, но переведу как буду писать для англоязычных... честно переведу).

П.С.: Кстати, по поводу слоёв... Есть одна библиотечка — RTTR. Меня на неё знакомый навёл буквально две недели назад. Выглядит очень достойно, хотя есть и избыточные, на мой взгляд, фичи. Подумываю изучить RTTR детальнее и даже списаться с автором. Если окажется, что его подходы лучше покрывают интересующий нас функционал, то нашу рефлексию уберём, и настроим прочие фичи (сериализацию, автогенерацию GUI, и т.д.) на базе API его библиотеки. Настроить всё для связки должно быть не очень трудно, архитектура с самого начала строилась модульной.

П,П.С.: Слушайте. как использовать тег code нормально? Он что-то дикое с кодом делает.

Явная имплементация на стороне прикладного кода выглядит очень по-детски. Весь смысл reflection в том, чтобы о ней знал только тот, кто ею пользуется, тогда как код, к которому применяется этот инструмент, оставался неизменным.
У вас же есть весьма богатый инструментарий для метапрограммирования.

Ну, в явной регистрации есть ещё и плюс — пользователь может зарегистрировать только нужные ему классы и их поля... К тому же, в С++ и не особо возможно сделать по-другому — разве что уже упомянутая тут несколько раз кодогенерация (кстати, тоже не самая глупая возможность, на самом деле).

Вообще, я вот смотрю сейчас на RTTR и всё сильнее склоняюсь к тому, чтобы скооперироваться в смысле рефлексии с её автором и над его кодом надстроить весь остальной функционал, связанный с генерацией GUI и сериализацией. В проекте сейчас единственный активный контрибутор (он же автор библиотеки), поэтому легко будет обсудить нужные для работы наших классов минимальные изменения.

Вообще, сейчас в связи с обсуждением читаю всякие статьи, и чем дальше, тем больше склоняюсь к тому, чтобы использовать кодогенерацию. Только вот проблема есть... Чтобы пользователь мог настроить кодогенерацию нужных данных для рефлексии, нужно помечать то, что требует генерации каким-нибудь образом. А единственный по-настоящему разумный способ сделать это, на мой взгляд, использовать атрибуты, которые появились не implementation specific только с С++11 (ссылка), и я пока не понял, есть ли возможность делать свои атрибуты... Но всё это касается лишь регистрации рефлексии. Генерирование GUI можно продолжать пилить, не переделывая соответствующую часть проекта.

Я напомню (а кому-то расскажу вновь): до сих пор есть такая штука как IRC. С тематическими техническими каналами, да. Где и по сей день можно найти и людей знающих, и энтузиастов.
#c в руснете, ##c++ в freenode.

Cпасибо за напоминание об IRC! Мне уже как-то советовали знающие люди глянуть про него, я глянул — и немного испугался... мм... аскетичности средств. Может, знаете где можно почитать с чего начать при использовании IRC? Ну, и вообще отлично было бы, если бы подсказали где можно глянуть как принято общаться в среде людей, использующих этот канал общения?
Я так понимаю, там логика такая, что можно бродкастить сообщения на разные группы пользователей?.. Хотя ладно, лучше не буду задавать профанские вопросы, и просто почитаю материалы по поводу.

П.С.: Вот что сходу нашлось по поводу введения в IRC. Выглядит достаточно неплохо — подойдёт?

С технической стороной проблем разобраться не составит, как мне кажется.
А этикет — типичный сетевой, он в общем-то оттуда и появился. Можно посмотреть на примеры общеприменимых правил навроде DALnet Netiquette Guide или How To Ask Questions The Smart Way

Нахрена такое надо? Если надо доступ к значениям по строковым ключам — есть же Dictionary/Map, в стандартной библиотеке.

Представьте только себе: возможность использовать поля классов по их строковым именам в рантайм!

Представил. Ужаснулся.

Мне сложно представить use-case, зато легко представить abuse.

Yegor Chumakov ответил ниже. Именно. Сериализация, автогенерация GUI, тестирование, ORM.

Почитал. Какая-то очень странная идея. ORM зло — поэтому давайте нафигачим тонны копи-пасты и сделаем свой ORM, но типа не ORM. В комментариях к этому посту выразили большую частью моих мыслей — что делать если этот метод нужно использовать для сотни таблиц.

Да, ORM, возможно, не напрямую отображает предметную область (взаимодействие с БД), но ведь если посмотреть реальное ООП приложение, рано или поздно данные, которые были получены из таблицы придётся передавать как-нибудь в объекты. А это значит, что от преобразования данных в объектное представление никак не обойтись. А если не обойтись, то рано или поздно придётся делать что-нибудь в духе ORM.

P.S.: Сам, если что, про ORM знаю только по лекциям в ВУЗе которые были давно и по трёхмесячным курсам в bionic university. Пусть более знающие люди отпишутся что думают.
P.P.S.: Кстати, в комментах на том ресурсе бывают попадаются весьма брутальные люди)

Никогда не видел чтобы кто-то пользовался сериализацией, например, в Яве. С другой стороны — знаком с протобуферами, которые не требую рефлексии.

Автогенерация UI — древняя мечта, которая не работала и не будет работать.

Тестирование — у меня работает без рефлексии. ЧЯДНТ?

ORM — одна из самый идиотских придумок, которые я видел. Делается набор «глупых» объектов (в них нет логики, только данные), пишется тонна XML (ну или аннотации), загружается гигантская библиотека которая начинает по-тормозному те объекты из бд загружать.

Большинство этих сценариев можно реализовать кодогенерацией, без засырания рантайма.

Какая категоричность... А какие-нибудь ссылки по темам можно почему «которая не работала и не будет работать»? А то я как-то полтора года работал на достаточно нехилом проекте, где UI для редактора в основном из кода генерировался. И слышал мысли от весьма неглупых коллег, что так вообще везде делают.
И ещё я видел как в одном малоизвестном движке... кажется Unity назвался, ага... очень даже норм работало и работает.

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

П.С.: И, нет, это не только желание во что бы то ни стало защитить свой проект. Это всего навсего грусть по поводу категоричного пессимизма без каких-либо то ни было серьёзных обоснований оного (хотя нет, вру, Oleksiy Protas ссылку дал).

По моей логике новое надо делать. А не снова и снова реализовывать старые провальные идеи, с тем же результатом.

Ваши «неглупые» коллеги сильно ошибаются когда утверждают что так _везде_ делают.

В начале хотел написать обидный комментарий типа «какой смысл выражать столь категорично мысли по поводу геймдева если ПХП программист». Потом глянул на опыт работы на linked in и... Да, я по-прежнему против безосновательной критики.

Опыт штука здоровская, но, как по мне, писать комментарии имеет смысл не чтобы блеснуть опытом и заявить свысока «вот фигня всё это», а чтобы им поделиться. Если «всё фигня» — то почему.

П.С.: А как тогда делают «не везде», когда нужен редактор для объектов с кучей полей? Я решения лучше кодогенерации не вижу. Если это не секрет, поделитесь своим опытом.

ну в qt c++, builder c++ зачем-то добавили мета-свойства, значит есть сценарии использования.

то есть, использование инструментов, которые экономят программисту кучу времени, не подпадает под понятие «здравый смысл»?

Борьба с глюками и заскоками Qt больше тратит времени чем экономит.

то есть, предлагаете не использовать библиотеки или фреймворки, а опираясь на здравый смысл и стандартную библиотеку, писать свои велосипеды?

Все проекты, в которых я учавствую так и делают. Весьма успешные проекты.

А вообще не воспринимайте близко к сердцу, я просто вспоминаю сколько боли из-за late binding виртуальных методов, а тут еще один уровень late binding-а наслаивается.

я просто вспоминаю сколько боли из-за late binding виртуальных методов

А что с ними не так? Типа, оверхед? Если так, то рефлексия часто требуется в нерелизном коде: внутренние редакторы, тестирования кода.

Что касается релизного кода (например, применение для сериализации данных). Тут, стоит заметить, ваша правда. Например, в тех же играх в релизном коде вряд ли потребуется возможность получения информации о начинке класса и смысла держать зверинец разных сериализаторов тоже нет (имеется один единственный сериализатор для генерирования сейвок). То же касается ORM.

Да, для поддержки этой концепции в релизном коде стоит придумать что-нибудь... Можно на шаблонах, но это сделает код уродливым... В общем, это только часть задач, для нерелизного кода рефлексия даёт, на мой взгляд, достаточно полезностей.

P.S.: Ясное дело, всё сказанное касается С++, в динамических языках вроде Java и C# рефлексия есть по-умолчанию (кстати, вопрос к знающим людям: от неё можно избавиться как-нибудь по желанию?).

Reflection же. Для ORM например это очень нужно.

Если для чего-то нужен Reflection — значит вам нужно странное.

Ну, юзкейсы рефлексии были описаны выше. Если так — значит эти задачи попадают в перечень странного...

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

Использование рефлексии превращает объекты в HashMap. Что есть глупость.

Отписался выше... Вот не понятен мне смысл писать такие комменты, чесслово! Почему глупость?.. Может быть, нет, я соглашусь если доводы разумные будут... Вы можете написать почему, а не писать бессмысленный коммент «всё говно»?

Глупость потому что найти реализацию Hashmap несложно.

Представьте только себе: возможность использовать поля классов по их строковым именам в рантайм! Какие это возможности открывает...
Ну и какие это возможности открывает? С точки зрения разработчиков, технология хороша, если она позволяет быстро писать эффективный и безглючный код. Если при этом её надо долго изучать, то проще написать самому, или найти workaround. С точки зрения игрока, всё должно быть просто и интуитивно понятно. Игрок не станет читать какие-то простыни с текстами, и разбираться в куче настроек, если это конечно не задрот.
С точки зрения разработчиков, технология хороша, если она позволяет быстро писать эффективный и безглючный код

Надеюсь, позволяет. С чего вы взяли что её нужно долго изучать? Можете глянуть в гуглдоке пример того, что требуется от разработчика. На мой взгляд, не так уж и страшно — и это пока только прототип.

А вы случайно не пытаетесь сделать что-то типа stackoverflow.com/...ost-fusion-map-field-name на Boost::Fusion?

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

Хотя за наводку спасибо, почитаю. Ещё про аналоги вот тут ребята написали: habrahabr.ru/post/257071. Там есть реально крутые решения и у них есть чему поучиться.

С++
+ опен сорц = моветон

робив таку штуку, називали «кеш»,
так от за движок взляли SQLite, який на чистим С, далі С++ обгортка (OMG).
А закінчилося діло так: SQLite + Java, і ніяких Сішанутих плюсів

Мм... Причём здесь SQLite? Почему open source и C++ это моветон? Ничего не понял...

Мій досвід не надто великий, але я б хотів допомогти в її створенні

Дякую що зацікавились. Пишіть у скайп: semenyakinVS

Цікаво, напишу Вам 1-2 травня, або маякніть мені, якщо я забуду, а ви згадаєте.

Підписатись на коментарі