MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
EventMultiplex.h
Go to the documentation of this file.
1/** @noop License Comment
2 * @file
3 * @copyright
4 * This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5 * If a copy of the MPL was not distributed with this file You can obtain one at
6 * https://mozilla.org/MPL/2.0/
7 *
8 * @author David Mórász
9 * @date 2025
10 */
11
12#pragma once
13
14#include "CoreMinimal.h"
15#include "Mcro/FunctionTraits.h"
17
18/**
19 * Glue together a regular function, a native event delegate and a dynamic multicast delegate, so a given API
20 * can serve
21 * - events via function override
22 * - C++ listeners via a native event delegate
23 * - Blueprint listeners via a dynamic multicast delegate
24 * with calling only a single class member.
25 *
26 * @param functionName The base name of the function which can be listened to with multiplexing
27 */
28#define MCRO_DYNAMIC_EVENT_MULTIPLEX(functionName) \
29 Mcro::Delegates::TNativeMultiplex<F##functionName> functionName##Multiplex \
30 { \
31 Mcro::Delegates::From(this, &MCRO_THIS_TYPE::functionName), \
32 Mcro::Delegates::From(functionName##Event) \
33 } \
34
35/**
36 * In case the multiplexed function returns a value instead of just returning void, add this macro below the dynamic
37 * multicast delegate declaration
38 *
39 * @param delegate The name of the dynamic multicast delegate
40 * @param type The return type of the multiplexed function
41 */
42#define MCRO_DYNAMIC_RETURN(delegate, type) \
43 template<> struct Mcro::Delegates::TReturnOverride_Struct<delegate> { using Type = type; }
44
45namespace Mcro::Delegates
46{
47 using namespace Mcro::Concepts;
48
49 namespace Detail
50 {
51 template <typename Return, typename... Args>
53 {
54 public:
55 using FunctionSignature = Return(Args...);
56 using EventSignature = void(Args...);
57 using FDelegate = TDelegate<FunctionSignature, FDefaultDelegateUserPolicy>;
58 using FEventDelegate = TDelegate<EventSignature, FDefaultDelegateUserPolicy>;
59
60 template <CSameAs<FEventDelegate>... Delegates>
61 TEventMultiplexBase(FDelegate&& function, Delegates&&... delegates)
62 : Multicast(delegates...)
63 , Function(function)
64 {}
65
66 TEventDelegate<void(Args...)> Multicast;
67
68 TEventDelegate<void(Args...)>* operator -> () const
69 {
70 return &Multicast;
71 }
72 protected:
74 };
75 }
76
77 template <typename T>
79
80 /**
81 * Glue together a regular function, a native event delegate and a dynamic multicast delegate, so a given API
82 * can serve
83 * - events via function override
84 * - C++ listeners via a native event delegate
85 * - Blueprint listeners via a dynamic multicast delegate
86 * with calling only a single class member.
87 *
88 * This is set up via the MCRO_DYNAMIC_EVENT_MULTIPLEX macro next to relevant class members.
89 */
90 template <CNonVoid Return, typename... Args>
91 class TEventMultiplex<Return(Args...)> : public Detail::TEventMultiplexBase<Return, Args...>
92 {
93 public:
94 template <CSameAs<FEventDelegate>... Delegates>
95 TEventMultiplex(FDelegate&& function, Delegates&&... delegates)
96 : Detail::TEventMultiplexBase<void, Args...>(function, delegates...)
97 {}
98
99 Return operator() (Args... args)
100 {
101 Return result = Function.Execute(args...);
102 Multicast.Broadcast(args...);
103 return result;
104 }
105
106 template <typename... OptionalObject> requires (sizeof...(OptionalObject) <= 1)
107 FDelegate Delegation(OptionalObject... object)
108 {
109 return From(object..., &TEventMultiplex::operator());
110 };
111 };
112
113 template <typename... Args>
114 class TEventMultiplex<void(Args...)> : public Detail::TEventMultiplexBase<void, Args...>
115 {
116 public:
117 template <CSameAs<FEventDelegate>... Delegates>
118 TEventMultiplex(FDelegate&& function, Delegates&&... delegates)
119 : Detail::TEventMultiplexBase<void, Args...>(function, delegates...)
120 {}
121
122 void operator ()(Args... args)
123 {
124 Function.Execute(args...);
125 Multicast.Broadcast(args...);
126 }
127
128 template <typename... OptionalObject> requires (sizeof...(OptionalObject) <= 1)
129 FDelegate Delegation(OptionalObject... object)
130 {
131 return From(object..., &TEventMultiplex::operator());
132 };
133 };
134
135 template <CDynamicMulticastDelegate Dynamic>
137 {
138 using Type = void;
139 };
140
141 template <typename Dynamic>
143
144 template <
146 typename Return = TReturnOverride<Dynamic>
147 >
154
155 template <
156 typename Dynamic,
157 typename Return = TReturnOverride<Dynamic>
158 >
160}
TEventMultiplexBase(FDelegate &&function, Delegates &&... delegates)
TDelegate< FunctionSignature, FDefaultDelegateUserPolicy > FDelegate
TEventDelegate< void(Args...)> Multicast
TDelegate< EventSignature, FDefaultDelegateUserPolicy > FEventDelegate
TEventDelegate< void(Args...)> * operator->() const
TEventMultiplex(FDelegate &&function, Delegates &&... delegates)
FDelegate Delegation(OptionalObject... object)
TEventMultiplex(FDelegate &&function, Delegates &&... delegates)
FDelegate Delegation(OptionalObject... object)
typename TReturnOverride_Struct< Dynamic >::Type TReturnOverride
TInferredDelegate< Function, Captures... > From(Function func, const Captures &... captures)
typename TNativeMultiplex_Struct< Dynamic, Return >::Type TNativeMultiplex
TFunctionFromTuple< Return, TFunction_Arguments< DstFunction > > TSetReturn