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);
82inline bool operator==(
const AbstractEventMetaType& lhs,
83 const AbstractEventMetaType& rhs)
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>
335#if Quotient_VERSION_MAJOR == 0
&& Quotient_VERSION_MINOR <= 9
375template <
typename EventT, EventClass BaseEventT,
typename ContentT =
void>
381 !std::is_same_v<ContentT,
void>,
382 "If you see this, you tried to use EventTemplate with the default"
383 " ContentT type, which is void. This default is only used with explicit"
384 " specialisations (see CallEvent, e.g.). Otherwise, if you don't intend"
385 " to use the content part of EventTemplate then you don't need"
386 " EventTemplate; just use the base event class directly");
387 using content_type = ContentT;
396 ContentT
content()
const {
return fromJson<ContentT>(
this->contentJson()); }
408#define QUO_BASE_EVENT(CppType_, BaseCppType_, ...)
409 friend class EventMetaType<CppType_>;
410 static inline EventMetaType<CppType_> BaseMetaType{
411 #CppType_, &BaseCppType_::BaseMetaType __VA_OPT__(, ) __VA_ARGS__
413 static_assert(&CppType_::BaseMetaType == &BaseMetaType,
414 #CppType_ " is wrong here - check for copy-pasta");
415 const AbstractEventMetaType& metaType() const override
436#define QUO_EVENT(CppType_, MatrixType_)
437 friend class EventMetaType<CppType_>;
438 static inline const EventMetaType<CppType_> MetaType{ #CppType_,
441 static_assert(&CppType_::MetaType == &MetaType,
442 #CppType_ " is wrong here - check for copy-pasta");
443 static inline const auto& TypeId = MetaType.matrixId;
444 const AbstractEventMetaType& metaType() const override
450#define QUO_CONTENT_GETTER_X(PartType_, PartName_, JsonKey_)
451 PartType_ PartName_() const
453 static const auto PartName_##JsonKey = JsonKey_;
454 return contentPart<PartType_>(PartName_##JsonKey);
465#define QUO_CONTENT_GETTER(PartType_, PartName_)
476#define DEFINE_SIMPLE_EVENT(Name_, Base_, TypeId_, ValueType_, GetterName_, JsonKey_)
477 constexpr inline auto Name_##ContentKey = JsonKey_##_L1;
479 : public ::Quotient::EventTemplate<
480 Name_, Base_, EventContent::SingleKeyValue<ValueType_, Name_##ContentKey>> {
483 using value_type = ValueType_;
484 using EventTemplate::EventTemplate;
491template <EventClass EventT>
492inline bool is(
const Event& e)
495 static_assert(requires { &EventT::metaType; },
496 "Event class doesn't have a public metaType() override - "
497 "did you misplace the QUO_*EVENT macro?");
498 if constexpr (requires { EventT::MetaType; }) {
499 return &e.metaType() == &EventT::MetaType;
501 const auto* p = &e.metaType();
503 if (p == &EventT::BaseMetaType)
505 }
while ((p = p->baseType) !=
nullptr);
517template <EventClass EventT,
typename BasePtrT>
521 return eptr && is<std::decay_t<EventT>>(*eptr)
522 ?
static_cast<EventT*>(std::to_address(eptr))
540template <EventClass EventT,
typename BaseEventT>
543 return eptr && is<std::decay_t<EventT>>(*eptr)
544 ? event_ptr_tt<EventT>(
static_cast<EventT*>(eptr.release()))
549 template <
typename FnT,
typename BaseT>
550 concept Invocable_With_Downcast =
551 EventClass<BaseT> && std::derived_from<std::remove_cvref_t<fn_arg_t<FnT>>, BaseT>;
554template <EventClass BaseT,
typename TailT>
557 if constexpr (std::is_invocable_v<TailT, BaseT>) {
559 }
else if constexpr (_impl::Invocable_With_Downcast<TailT, BaseT>) {
560 using event_type = fn_arg_t<TailT>;
561 if (is<std::decay_t<event_type>>(event))
562 return tail(
static_cast<event_type>(event));
563 return std::invoke_result_t<TailT, event_type>();
565 return std::forward<TailT>(tail);
569template <
typename FnT1,
typename... FnTs>
570inline auto switchOnType(
const EventClass
auto& event, FnT1&& fn1, FnTs&&... fns)
572 using event_type1 = fn_arg_t<FnT1>;
573 if (is<std::decay_t<event_type1>>(event))
574 return fn1(
static_cast<event_type1>(event));
575 return switchOnType(event, std::forward<FnTs>(fns)...);
586Q_DECLARE_METATYPE(Quotient::Event*)
587Q_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
auto eventCast(const BasePtrT &eptr) -> decltype(static_cast< EventT * >(std::to_address(eptr)))
Cast the event pointer down in a type-safe way.
event_ptr_tt< EventT > makeEvent(ArgTs &&... args)
Create an event of arbitrary type from its arguments.
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)
bool operator==(const LoginFlow &lhs, const LoginFlow &rhs)
event_ptr_tt< EventT > loadEvent(const QJsonObject &fullJson)
Create an event with proper type from a JSON object.