Этому был посвящён целый пункт.
Но если вкратце: функторы сравниваются по адресу объекта, методы (функции-члены) — по адресу экземпляра класса (которому они принадлежат) и своему адресу.
Естественно, сравниваются только однотипные объекты: как функторы, так и методы классов. Разнотипные обработчики считаются неравными.
Не очень понятно, при чём здесь C# (которым я, кстати, во многом вдохновлялся), если в нём, в отличие от C++, данный механизм встроен в язык. Насчёт «ради Qt» тоже не очень понятно, потому что данная реализация позволяет как раз не использовать сторонние библиотеки и фреймворки (по крайней мере, только ради сигналов).
А какая у Вас версия Qt? Перепроверил — всё подтвердилось. Я сейчас использую Qt5.6.1-1 (надо бы, конечно, обновиться...). Компилятор — VS++14 (соответственно, и MSBuild в качестве сборщика).
Ошибка на этапе сборке.
При описанном в cpp-файле классе с директивой Q_OBJECT выдаётся предупреждение
Warning MSB8017 A circular dependency has been detected while executing custom build commands for item "GeneratedFiles\Debug\filename.moc". This may cause incremental build to work incorrectly.
и все методы, которые должны быть сгенерированы moc'ом (metaObject, qt_metacast и т.д.), становятся unresolved, вызывая соответствующие ошибки. Кроме того в Generated Files, где под каждую конфигурацию должен присутствовать сгенерированный файлик moc_filename.cpp, находится только несуществующий filename.moc.
Возможно, дело именно в MSBuild'е или его взаимодействии с Qt. Если это и вправду так, нужно будет действительно убрать этот пункт из недостатков.
C++11 это вы преуменьшаете :) std::shared_mutex ----> C++17.
Действительно, размахнулся что-то.
Не собралось под GCC из-за некоторого несоответствия стандарту
Это всё моя привычка разработки под VC. Надо будет поисправлять.
У меня впечатление, что shared_ptr для Holder не обязателен и я бы попытался заменить его на unique_ptr в списке обработчиков + сырой readonly указатель во всех остальных местах.
Немного не понял. В списке обработчиков как раз не Holder, а EventHandler, в котором уже Holder. Вы всё-таки при EventHandler?
лучше использовать std::make_shared
там, где применяется не он, используется private конструктор (в Holder'ах, например, это сделано для правильной инициализации поля m_me).
Некоторые внутренние типы лучше спрятать из публичного интерфейса
так, вроде убраны же в анонимные namespace'ы.
А вообще, за замечания спасибо)
В контексте GUI ожидается граф сцены, в ивенте содержатся координаты мыши, а ивент проходится по графу сцены.
Как я уже сказал, я не считаю этот подход равнозначным. Как Вы верно заметили, даже в Qt реализованы они оба (и The Event System, и Signals & Slots). Кроме того, use case'ов много (не только лишь GUI), не везде удобно одно и то же.
Тогда очевидный вопрос зачем? Когда есть множество реализаций тех же сингалов?
Согласен. Как минимум, когда не хочется/можется подключать библиотеку с очередной реализаций сигналов. Возможно, кому-то будет удобно и полезно. Плюс, небольшая демонстрация разных возможностей С++ (но это тоже скорее доп).
Данная реализация как раз представляет собой нечто близкое к 'Signals & Slots', а не к 'The Event System'; последнее ближе к очереди (циклу) событий, там объекты взаимодействуют через цикл событий, а не напрямую. На мой взгляд, это всё же другой подход.
Почему для сравнения берутся сигналы из Qt, а не сигналы из Boost?
Вообще не было цели сравнивать хоть с чем-то. Это, скорее, просто бонус, вызванный тем, что с сигналами/слотами Qt мне приходилось работать (а с сигналами из boost нет).
если честно, не понял, зачем там void().
разве для составления unused (который по сути можно объявить как bool unused[] =) не достаточно будет только параметра true?
Но если вкратце: функторы сравниваются по адресу объекта, методы (функции-члены) — по адресу экземпляра класса (которому они принадлежат) и своему адресу.
Естественно, сравниваются только однотипные объекты: как функторы, так и методы классов. Разнотипные обработчики считаются неравными.
Явно есть, куда двигаться дальше.
Спасибо; недостаток убираю.
А вот тут не совсем понятно, почему событие должно обрабатывать исключения в клиентском коде (если можно так назвать обработчики).
Ошибка на этапе сборке.
При описанном в cpp-файле классе с директивой Q_OBJECT выдаётся предупреждение и все методы, которые должны быть сгенерированы moc'ом (metaObject, qt_metacast и т.д.), становятся unresolved, вызывая соответствующие ошибки. Кроме того в Generated Files, где под каждую конфигурацию должен присутствовать сгенерированный файлик moc_filename.cpp, находится только несуществующий filename.moc.
Возможно, дело именно в MSBuild'е или его взаимодействии с Qt. Если это и вправду так, нужно будет действительно убрать этот пункт из недостатков.
Это всё моя привычка разработки под VC. Надо будет поисправлять.
Немного не понял. В списке обработчиков как раз не Holder, а EventHandler, в котором уже Holder. Вы всё-таки при EventHandler?
там, где применяется не он, используется private конструктор (в Holder'ах, например, это сделано для правильной инициализации поля m_me).
так, вроде убраны же в анонимные namespace'ы.
А вообще, за замечания спасибо)
Как я уже сказал, я не считаю этот подход равнозначным. Как Вы верно заметили, даже в Qt реализованы они оба (и The Event System, и Signals & Slots). Кроме того, use case'ов много (не только лишь GUI), не везде удобно одно и то же.
Согласен. Как минимум, когда не хочется/можется подключать библиотеку с очередной реализаций сигналов. Возможно, кому-то будет удобно и полезно. Плюс, небольшая демонстрация разных возможностей С++ (но это тоже скорее доп).
Данная реализация как раз представляет собой нечто близкое к 'Signals & Slots', а не к 'The Event System'; последнее ближе к очереди (циклу) событий, там объекты взаимодействуют через цикл событий, а не напрямую. На мой взгляд, это всё же другой подход.
Вообще не было цели сравнивать хоть с чем-то. Это, скорее, просто бонус, вызванный тем, что с сигналами/слотами Qt мне приходилось работать (а с сигналами из boost нет).
разве для составления unused (который по сути можно объявить как bool unused[] =) не достаточно будет только параметра true?