UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
QuartzCompileTimeVisitor.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include <type_traits>
7
8// forwards
10{
11 // Notes on the Visitor Pattern (https://en.wikipedia.org/wiki/Visitor_pattern)
12 // this is a pattern that helps solve two things:
13 // - adds operations for a class without modifying the class itself
14 // (and more importantly for Quartz's use-case:)
15 // - implements Double-Dispatch (https://en.wikipedia.org/wiki/Double_dispatch)
16 //
17 // C++ supports single-dispatch through polymorphism, where a concrete function
18 // called depends on the dynamic type of a SINGLE object.
19 //
20 // i.e.: MyBasePtr->DoThing(MyConcreteType);
21 //
22 // Double dispatch is being able resolve to a concrete function for how
23 // TWO dynamic types should interact
24 //
25 // i.e.: MyBaseA_ptr->DoThing(MyBaseB_ptr)
26 //
27 // where we could resolve to different concrete functions for each combination of
28 // the RUNTIME TYPES of objects derived from MyBaseA and MyBaseB.
29 //
30 // Concretely, Quartz has metronome listeners, command listeners, etc
31 // and has things that can be both a metronome and a command listener.
32 //
33 // The DOWNSIDE to the visitor pattern is the element (or listener) types must be known
34 // at compile time. This makes it hard to write reusable objects like command queues.
35 //
36 // This implementation uses some template metaprogramming to abstract away the visitor pattern
37 // and let client code build reusable things like command queues and FSMs without needing to know
38 // the final concrete types.
39 //
40 // It also helps avoid some diamond inheritance problems that are easy to run into
41 // when attempting to have a "consumer" base type, and then types that can be multiple
42 // kinds of consumers.
43
44
56 template <typename... Ts>
58 {
59 private:
80 // Forward declaration for the primary template
81 template <typename... Interfaces>
82 class TVisitorInterface;
83
84 // Specialization for the base case
85 template <typename Interface>
86 class TVisitorInterface<Interface>
87 {
88 public:
89 virtual ~TVisitorInterface<Interface>() = default;
90 virtual void Visit(Interface&) {};
91 }; // class TVisitorInterface
92
93 // Specialization for the recursive case
94 template <typename First, typename... Rest>
95 class TVisitorInterface<First, Rest...> : public TVisitorInterface<Rest...>
96 {
97 public:
98 // Use Visit methods from the base class
99 using TVisitorInterface<Rest...>::Visit;
100
101 // Override Visit for the first type in the pack
102 virtual void Visit(First&) {};
103
104 }; // class TVisitorInterface
105
106 protected:
107 class IVisitorBase : public TVisitorInterface<Ts...>
108 {
109 // todo: comment about the inherited interface
110 }; // class IVisitorBase
111
112 /*
113 IListenerBase:
114 * this should not be inherited from directly, but is public for
115 * polymorphic access to client listeners via IListenerBase*
116 */
117
119 {
120 public:
121 virtual ~IListenerBase() = default;
122 virtual void Accept(IVisitorBase&) = 0;
123
124 }; // class IListenerBase
125
126 public:
136 template <typename... ListenerInterfaces>
137 class TElementBase : public IListenerBase, public ListenerInterfaces...
138 {
139 public:
140 virtual void Accept(IVisitorBase& InVisitor) override final
141 {
142 (..., (void)InVisitor.Visit(*static_cast<ListenerInterfaces*>(this)));
143 }
144 }; // class TElementBase
145
146 protected:
152 template <class TargetInterface>
154 {
155 public:
156 // Bring all versions of Visit into the scope
157 // otherwise the compiler complains we hide the ones we aren't overriding
158 using IVisitorBase::Visit;
159
161
163 : Lambda (MoveTempIfPossible(InLambda))
164 {}
165
166 virtual ~TVisitWithLambda() override = default;
167
168 virtual void Visit(TargetInterface& InTarget) override final
169 {
170 if(Lambda)
171 {
172 Lambda(InTarget);
173 }
174 }
175
176 private:
178 }; // class TVisitWithLambda
179 }; // class TVisitorPatternBase
180} // namespace Audio::Quartz::PrivateDefs
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
decltype(auto) Visit(Func &&Callable, Variants &&... Args)
Definition TVariant.h:271
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTempIfPossible(T &&Obj) noexcept
Definition UnrealTemplate.h:538
UEBinkAudioDecodeInterface * Interface
Definition binka_ue_decode_test.cpp:24
Definition QuartzCompileTimeVisitor.h:108
Definition QuartzCompileTimeVisitor.h:138
virtual void Accept(IVisitorBase &InVisitor) override final
Definition QuartzCompileTimeVisitor.h:140
virtual void Visit(TargetInterface &InTarget) override final
Definition QuartzCompileTimeVisitor.h:168
Definition QuartzCompileTimeVisitor.h:58
Definition AndroidPlatformMisc.h:14
Definition QuartzCommandQueue.h:13