8#include <Quotient/converters.h>
9#include <Quotient/function_traits.h>
32template <
typename EventT,
typename BaseEventT = Event>
35template <EventClass EventT>
36bool is(
const Event& e);
177template <EventClass EventT,
typename... ArgTs>
180 return std::make_unique<EventT>(std::forward<ArgTs>(args)...);
183template <EventClass EventT>
186 if constexpr (requires { EventT::MetaType; })
187 return EventT::MetaType;
189 return EventT::BaseMetaType;
197template <EventClass EventT>
200 return mostSpecificMetaType<EventT>().loadFrom(
201 fullJson, fullJson[TypeKey].toString());
209template <EventClass EventT>
211 const auto&... otherBasicJsonParams)
213 return mostSpecificMetaType<EventT>().loadFrom(
214 EventT::basicJson(matrixType, otherBasicJsonParams...), matrixType);
307 template <
typename T,
typename KeyT>
320 template <
typename T,
typename KeyT>
371template <
typename EventT, EventClass BaseEventT,
typename ContentT =
void>
377 !std::is_same_v<ContentT,
void>,
378 "If you see this, you tried to use EventTemplate with the default"
379 " ContentT type, which is void. This default is only used with explicit"
380 " specialisations (see CallEvent, e.g.). Otherwise, if you don't intend"
381 " to use the content part of EventTemplate then you don't need"
382 " EventTemplate; just use the base event class directly");
383 using content_type = ContentT;
392 ContentT
content()
const {
return fromJson<ContentT>(
this->contentJson()); }
404#define QUO_BASE_EVENT(CppType_, BaseCppType_, ...)
405 friend class EventMetaType<CppType_>;
406 static inline auto BaseMetaType =
407 EventMetaType<CppType_>(&BaseCppType_::BaseMetaType __VA_OPT__(, ) __VA_ARGS__);
408 static_assert(&CppType_::BaseMetaType == &BaseMetaType,
409 #CppType_ " is wrong here - check for copy-pasta");
410 const AbstractEventMetaType &metaType() const override { return BaseMetaType; }
428#define QUO_EVENT(CppType_, MatrixType_)
429 friend class EventMetaType<CppType_>;
430 static inline const auto MetaType = EventMetaType<CppType_>(&BaseMetaType, MatrixType_);
431 static_assert(&CppType_::MetaType == &MetaType,
432 #CppType_ " is wrong here - check for copy-pasta");
433 static inline const auto &TypeId = MetaType.matrixId;
434 const AbstractEventMetaType &metaType() const override { return MetaType; }
437#define QUO_CONTENT_GETTER_X(PartType_, PartName_, JsonKey_)
438 PartType_ PartName_() const
440 static const auto PartName_##JsonKey = JsonKey_;
441 return contentPart<PartType_>(PartName_##JsonKey);
452#define QUO_CONTENT_GETTER(PartType_, PartName_)
463#define DEFINE_SIMPLE_EVENT(Name_, Base_, TypeId_, ValueType_, GetterName_, JsonKey_)
464 constexpr inline auto Name_##ContentKey = JsonKey_##_L1;
466 : public ::Quotient::EventTemplate<
467 Name_, Base_, EventContent::SingleKeyValue<ValueType_, Name_##ContentKey>> {
470 using value_type = ValueType_;
471 using EventTemplate::EventTemplate;
478template <EventClass EventT>
479inline bool is(
const Event& e)
482 static_assert(requires { &EventT::metaType; },
483 "Event class doesn't have a public metaType() override - "
484 "did you misplace the QUO_*EVENT macro?");
485 if constexpr (requires { EventT::MetaType; }) {
486 return &e.metaType() == &EventT::MetaType;
488 const auto* p = &e.metaType();
490 if (p == &EventT::BaseMetaType)
492 }
while ((p = p->baseType) !=
nullptr);
504template <EventClass EventT>
507 return eptr && is<std::decay_t<EventT>>(*eptr)
508 ?
static_cast<EventT*>(std::to_address(eptr))
526template <EventClass EventT,
typename BaseEventT>
529 return eptr && is<std::decay_t<EventT>>(*eptr)
530 ? event_ptr_tt<EventT>(
static_cast<EventT*>(eptr.release()))
535 template <
typename FnT,
typename BaseT>
536 concept Invocable_With_Downcast =
537 EventClass<BaseT> && std::derived_from<std::remove_cvref_t<fn_arg_t<FnT>>, BaseT>;
540template <EventClass BaseT,
typename TailT>
543 if constexpr (std::is_invocable_v<TailT, BaseT>) {
545 }
else if constexpr (_impl::Invocable_With_Downcast<TailT, BaseT>) {
546 using event_type = fn_arg_t<TailT>;
547 if (is<std::decay_t<event_type>>(event))
548 return tail(
static_cast<event_type>(event));
549 return std::invoke_result_t<TailT, event_type>();
551 return std::forward<TailT>(tail);
555template <
typename FnT1,
typename... FnTs>
556inline auto switchOnType(
const EventClass
auto& event, FnT1&& fn1, FnTs&&... fns)
558 using event_type1 = fn_arg_t<FnT1>;
559 if (is<std::decay_t<event_type1>>(event))
560 return fn1(
static_cast<event_type1>(event));
561 return switchOnType(event, std::forward<FnTs>(fns)...);
572Q_DECLARE_METATYPE(Quotient::Event*)
573Q_DECLARE_METATYPE(
const Quotient::Event*)
A template base class to derive your event type from.
EventTemplate(const QJsonObject &json)
EventTemplate(const ContentT &c)
#define QUO_CONTENT_GETTER_X(PartType_, PartName_, JsonKey_)
#define QUO_EVENT(CppType_, MatrixType_)
Supply event metatype information in (specific) event types.
auto eventCast(event_ptr_tt< BaseEventT > &&eptr)
Cast the event pointer down in a type-safe way, with moving.
constexpr auto ContentKey
event_ptr_tt< EventT > makeEvent(ArgTs &&... args)
Create an event of arbitrary type from its arguments.
auto eventCast(const auto &eptr) -> decltype(static_cast< EventT * >(std::to_address(eptr)))
Cast the event pointer down in a type-safe way.
event_ptr_tt< EventT > loadEvent(const QString &matrixType, const auto &... otherBasicJsonParams)
Create an event from a type string and content JSON.
constexpr const auto & mostSpecificMetaType()
auto switchOnType(const EventClass auto &event, FnT1 &&fn1, FnTs &&... fns)
constexpr auto UnsignedKey
auto switchOnType(const BaseT &event, TailT &&tail)
event_ptr_tt< EventT > loadEvent(const QJsonObject &fullJson)
Create an event with proper type from a JSON object.