MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
ValueThunk.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#include "CoreMinimal.h"
14#include "Mcro/Concepts.h"
15#include "Mcro/FunctionTraits.h"
16#include "Mcro/Templates.h"
17
19{
20 using namespace Mcro::Concepts;
21 using namespace Mcro::FunctionTraits;
22 using namespace Mcro::Templates;
23
24 /** @brief Options for value thunks */
26 {
27 /**
28 * @brief
29 * If Memoize is true and associated value thunk is functional, cache the result of the first invocation.
30 * This makes it basically a "lazy value"
31 */
32 bool Memoize = false;
33 };
34
35 /**
36 * @brief
37 * Either a singular value of T, or a function returning T. It's very similar to TAttribute, however it doesn't
38 * rely on delegates, and has implicit conversions. TValueThunk owns its wrapped value.
39 */
40 template <typename T>
42 {
43 template <typename Other>
44 friend struct TValueThunk;
45
46 using FunctionStorage = std::conditional_t<CCopyConstructible<T>, TFunction<T()>, TUniqueFunction<T()>>;
47
48 template <CDefaultInitializable = T>
49 TValueThunk() : bIsSet(true) {}
50
51 template <CCopyConstructible = T>
52 TValueThunk(T const& value) : Storage(value), bIsSet(true) {};
53
54 template <CConvertibleTo<T> Other, CCopyConstructible = T>
56 : bIsSet(other.bIsSet)
57 , Options(other.Options)
58 , Function(other.Function)
59 {
60 if (other.bIsSet) Storage = other.Storage;
61 };
62
63 template <CMoveConstructible = T>
64 TValueThunk(T&& value) : Storage(FWD(value)), bIsSet(true) {};
65
66 template <CMoveConstructible = T>
68 : bIsSet(other.bIsSet)
69 , Options(MoveTemp(other.Options))
70 , Function(MoveTemp(other.Function))
71 {
72 if (other.bIsSet) Storage = MoveTemp(other.Storage);
73 };
74
75 template <CFunctorObject Functor>
76 requires CConvertibleTo<TFunction_ReturnDecay<Functor>, T>
77 TValueThunk(Functor&& value, FValueThunkOptions const& options = {})
78 : Options(options)
79 , Function(FWD(value))
80 {};
81
82 private:
83 void Evaluate() const
84 {
85 if (Function && (!Options.Memoize || !bIsSet))
86 {
87 Storage = Function();
88 bIsSet = true;
89 }
90 }
91
92 public:
93 /** @brief Evaluate the optional functor and get the cached result */
94 T& Get() { Evaluate(); return Storage; }
95
96 /** @brief Evaluate the optional functor and get the cached result */
97 T const& Get() const { Evaluate(); return Storage; }
98
99 /** @brief Evaluate the optional functor and move the cached result */
100 T&& Steal() && { Evaluate(); return MoveTemp(Storage); }
101
102 /** @brief Get a cached/last result without calling the optional functor */
103 T& GetLast() { return Storage; }
104
105 /** @brief Get a cached/last result without calling the optional functor */
106 T const& GetLast() const { return Storage; }
107
108 /** @brief Move a cached/last result without calling the optional functor */
109 T&& StealLast() && { return MoveTemp(Storage); }
110
111 operator T& () { return Get(); }
112 operator T const& () const { return Get(); }
113 operator T&& () && { return Steal(); }
114
115 bool IsSet() const { return bIsSet; }
116
117 template <CFunctorObject Functor>
118 requires CConvertibleTo<TFunction_ReturnDecay<Functor>, T>
119 TValueThunk& operator = (Functor&& value)
120 {
121 bIsSet = false;
122 Function = value;
123 return *this;
124 }
125
126 template <CConvertibleTo<T> Other>
127 requires (!CIsTemplate<Other, TValueThunk>)
128 TValueThunk& operator = (Other&& value)
129 {
130 bIsSet = true;
131 Function.Reset();
132 Storage = value;
133 return *this;
134 }
135
136 private:
137 mutable T Storage {};
138 mutable bool bIsSet = false;
139 FValueThunkOptions Options {};
140 FunctionStorage Function {};
141 };
142}
This header exists because STL headers in Android doesn't define STL concepts (other than same_as whi...
#define FWD(...)
Shorten forwarding expression with this macro so one may not need to specify explicit type.
Definition Macros.h:100
This namespace provides templating utilities and introspection into template instantiations.
Definition Templates.h:21
Options for value thunks.
Definition ValueThunk.h:26
bool Memoize
If Memoize is true and associated value thunk is functional, cache the result of the first invocation...
Definition ValueThunk.h:32
Either a singular value of T, or a function returning T. It's very similar to TAttribute,...
Definition ValueThunk.h:42
T && StealLast() &&
Move a cached/last result without calling the optional functor.
Definition ValueThunk.h:109
std::conditional_t< CCopyConstructible< T >, TFunction< T()>, TUniqueFunction< T()> > FunctionStorage
Definition ValueThunk.h:46
T & Get()
Evaluate the optional functor and get the cached result.
Definition ValueThunk.h:94
TValueThunk & operator=(Functor &&value)
Definition ValueThunk.h:119
T const & Get() const
Evaluate the optional functor and get the cached result.
Definition ValueThunk.h:97
TValueThunk(T const &value)
Definition ValueThunk.h:52
TValueThunk(TValueThunk< Other > const &other)
Definition ValueThunk.h:55
TValueThunk(Functor &&value, FValueThunkOptions const &options={})
Definition ValueThunk.h:77
TValueThunk(TValueThunk &&other)
Definition ValueThunk.h:67
T && Steal() &&
Evaluate the optional functor and move the cached result.
Definition ValueThunk.h:100
T const & GetLast() const
Get a cached/last result without calling the optional functor.
Definition ValueThunk.h:106
T & GetLast()
Get a cached/last result without calling the optional functor.
Definition ValueThunk.h:103