MCRO
C++23 utilities for Unreal Engine.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
FunctionTraits.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 <utility>
15
16#include "CoreMinimal.h"
17#include "Tuples.h"
18
19#include "Mcro/Concepts.h"
20
22{
23 using namespace Mcro::Concepts;
24 using namespace Mcro::Tuples;
25
26 /** @brief Concept constraining input T to a lambda function or a functor object. */
27 template <typename T>
28 concept CFunctorObject = requires { &std::decay_t<T>::operator(); };
29
30 namespace Detail
31 {
32 template <typename ReturnIn, typename... Args>
34 {
35 static constexpr size_t ArgumentCount = sizeof...(Args);
36
37 using Return = ReturnIn;
38 using ReturnDecay = std::decay_t<ReturnIn>;
39
40 /** The input parameters of the function as a tuple type. Types are not decayed. */
41 using Arguments = TTuple<Args...>;
42
43 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
44 using ArgumentsDecay = TTuple<typename TDecay<Args>::Type...>;
45
46 /** The pure function signature with other information stripped from it */
47 using Signature = Return(Args...);
48
49 template <int I>
50 using Arg = typename TTupleElement<I, Arguments>::Type;
51
52 template <int I>
53 using ArgDecay = typename TTupleElement<I, ArgumentsDecay>::Type;
54 };
55 }
56
57 /**
58 * @brief
59 * Get signature information about any function declaring type (function pointer or functor
60 * structs including lambda functions). It should be used in other templates.
61 *
62 * @tparam T the inferred type of the input function. 99% of cases this should be inferred.
63 */
64 template <typename T>
66 {
67 static constexpr size_t ArgumentCount = 0;
68 static constexpr bool IsFunction = false;
69 static constexpr bool IsPointer = false;
70 static constexpr bool IsFunctor = false;
71 static constexpr bool IsMember = false;
72 static constexpr bool IsConst = false;
73 };
74
75 /** @brief Specialization for functor structs / lambda functions. */
76 template <CFunctorObject T>
77 struct TFunctionTraits<T> : TFunctionTraits<decltype(&std::decay_t<T>::operator())>
78 {
79 static constexpr bool IsFunction = true;
80 static constexpr bool IsPointer = false;
81 static constexpr bool IsFunctor = true;
82 static constexpr bool IsMember = false;
83 static constexpr bool IsConst = false;
84 };
85
86 /** @brief Specialization extracting the types from the compound function pointer type of a const member function. */
87 template <typename ClassIn, typename ReturnIn, typename... Args>
88 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...) const> : Detail::TFunctionMeta<ReturnIn, Args...>
89 {
90 using Class = ClassIn;
91 static constexpr bool IsFunction = true;
92 static constexpr bool IsPointer = true;
93 static constexpr bool IsFunctor = false;
94 static constexpr bool IsMember = true;
95 static constexpr bool IsConst = true;
96 };
97
98 /** @brief Specialization extracting the types from the compound function pointer type of a member function. */
99 template <typename ClassIn, typename ReturnIn, typename... Args>
100 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
101 {
102 using Class = ClassIn;
103 static constexpr bool IsFunction = true;
104 static constexpr bool IsPointer = true;
105 static constexpr bool IsFunctor = false;
106 static constexpr bool IsMember = true;
107 static constexpr bool IsConst = false;
108 };
109
110 /** @brief Specialization extracting the types from the compound function pointer type. */
111 template <typename ReturnIn, typename... Args>
112 struct TFunctionTraits<ReturnIn(*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
113 {
114 static constexpr bool IsFunction = true;
115 static constexpr bool IsPointer = true;
116 static constexpr bool IsFunctor = false;
117 static constexpr bool IsMember = false;
118 static constexpr bool IsConst = false;
119 };
120
121 /** @brief Specialization extracting the types from the compound function type. */
122 template <typename ReturnIn, typename... Args>
123 struct TFunctionTraits<ReturnIn(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
124 {
125 static constexpr bool IsFunction = true;
126 static constexpr bool IsPointer = false;
127 static constexpr bool IsFunctor = false;
128 static constexpr bool IsMember = false;
129 static constexpr bool IsConst = false;
130 };
131
132 /** @brief Shorthand for getting a tuple representing the function arguments. */
133 template <typename T>
135
136 /** @brief Shorthand for getting a tuple representing the decayed function arguments. */
137 template <typename T>
139
140 /** @brief Shorthand for getting a type of a function argument at given position I. */
141 template <typename T, int I>
142 using TFunction_Arg = typename TFunctionTraits<std::decay_t<T>>::template Arg<I>;
143
144 /** @brief Shorthand for getting a decayed type of a function argument at given position I. */
145 template <typename T, int I>
146 using TFunction_ArgDecay = typename TFunctionTraits<std::decay_t<T>>::template ArgDecay<I>;
147
148 /** @brief Shorthand for getting a function argument count. */
149 template <typename T>
150 inline constexpr size_t TFunction_ArgCount = TFunctionTraits<std::decay_t<T>>::ArgumentCount;
151
152 /** @brief Shorthand for getting a function return type. */
153 template <typename T>
155
156 /** @brief Shorthand for getting a function return type discarding qualifiers. */
157 template <typename T>
159
160 /** @brief Shorthand for getting a pur function signature. */
161 template <typename T>
163
164 template <typename T>
165 concept CFunction_IsMember = TFunctionTraits<std::decay_t<T>>::IsMember;
166
167 /** @brief Shorthand for getting the class of a member function. */
168 template <CFunction_IsMember T>
170
171 /** @brief Shorthand for getting the constness of a member function. */
172 template <typename T>
173 concept CFunction_IsConst = TFunctionTraits<std::decay_t<T>>::IsConst;
174
175 /** @brief A concept accepting any function like entity (function pointer or functor object) */
176 template <typename T>
177 concept CFunctionLike = TFunctionTraits<std::decay_t<T>>::IsFunction;
178
179 /** @brief A concept accepting function pointer types */
180 template <typename T>
181 concept CFunctionPtr = TFunctionTraits<std::decay_t<T>>::IsPointer;
182
183 template <typename Class, typename Function>
185 && (CDerivedFrom<Class, TFunction_Class<Function>> || CSameAs<Class, TFunction_Class<Function>>)
186 ;
187
188 namespace Detail
189 {
190 template <typename Return, typename Tuple, size_t... Indices>
191 using TFunctionFromTupleIndices = Return(typename TTupleElement<Indices, Tuple>::Type...);
192
193 template <typename Return, typename Tuple>
195 {
196 template <size_t... Indices>
197 static consteval TFunctionFromTupleIndices<Return, Tuple, Indices...>* Compose(std::index_sequence<Indices...>&&);
198
199 using Type = std::remove_pointer_t<decltype(
200 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value>{})
201 )>;
202 };
203 }
204
205 /** @brief Compose a function type from a tuple of arguments and a return type */
206 template <typename Return, typename Tuple>
208
209 /** @brief Override the return type of an input function signature */
210 template <typename Return, typename DstFunction>
212
213 /** @brief Override the return type of an input function signature, and discard its qualifiers */
214 template <typename Return, typename DstFunction>
216
217 /** @brief Copy the return type from source function signature to the destination one */
218 template <typename SrcFunction, typename DstFunction>
220
221 /** @brief Copy the return type from source function signature to the destination one, and discard its qualifiers */
222 template <typename SrcFunction, typename DstFunction>
224
225 namespace Detail
226 {
227 template<typename Function, size_t... Sequence>
229 Function&& function,
230 TFunction_Arguments<Function> const& arguments,
231 std::index_sequence<Sequence...>&&
232 )
233 {
234 return function(arguments.template Get<Sequence>()...);
235 }
236
237 template<typename Object, typename Function, size_t... Sequence>
239 Object* object,
240 Function&& function,
241 TFunction_Arguments<Function> const& arguments,
242 std::index_sequence<Sequence...>&&
243 )
244 {
245 return (object->*function)(arguments.template Get<Sequence>()...);
246 }
247 }
248
249 /**
250 * @brief
251 * A clone of std::apply for Unreal tuples which also supports function pointers.
252 * TL;DR: It calls a function with arguments supplied from a tuple.
253 */
254 template<typename Function>
256 {
258 Forward<Function>(function), arguments,
259 std::make_index_sequence<TFunction_ArgCount<Function>>()
260 );
261 }
262
263 /**
264 * @brief
265 * A clone of std::apply for Unreal tuples which also supports function pointers. This overload can bind an object
266 * TL;DR: It calls a function with arguments supplied from a tuple.
267 */
268 template<CFunctionPtr Function, CHasFunction<Function> Object>
269 TFunction_Return<Function> InvokeWithTuple(Object* object, Function&& function, TFunction_Arguments<Function> const& arguments)
270 {
272 object,
273 Forward<Function>(function), arguments,
274 std::make_index_sequence<TFunction_ArgCount<Function>>()
275 );
276 }
277
278 /**
279 * @brief
280 * Tests if a provided class member function pointer instance (not type!) is indeed an instance member method.
281 * Negating it can assume static class member function
282 */
283 template <auto FuncPtr>
284 concept CInstanceMethod = requires(
285 TFunction_Class<decltype(FuncPtr)>* instance,
286 TFunction_Arguments<decltype(FuncPtr)> argsTuple
287 ) {
288 InvokeWithTuple(instance, FuncPtr, argsTuple);
289 };
290
291 /**
292 * @brief
293 * Defers a set of arguments for a function call later with its first argument. This is useful for developing
294 * fluent API operators.
295 */
296 template <auto FuncPtr, CFunctionPtr Function = decltype(FuncPtr)>
297 requires (
298 CFunctionPtr<decltype(FuncPtr)>
299 && TFunction_ArgCount<decltype(FuncPtr)> > 0
300 )
302 {
306
307 template <typename... Args>
309 : Storage(Forward<Args>(args)...)
310 {}
311
312 template <CConvertibleToDecayed<FirstArg> FirstArgRef>
313 Return operator () (FirstArgRef&& arg)
314 {
315 auto args = arg >> Storage;
316 return InvokeWithTuple<Function>(FuncPtr, args);
317 }
318
319 private:
320 ExtraArgs Storage;
321 };
322}
This header exists because STL headers in Android doesn't define STL concepts (other than same_as whi...
A concept accepting any function like entity (function pointer or functor object)
A concept accepting function pointer types.
Shorthand for getting the constness of a member function.
Concept constraining input T to a lambda function or a functor object.
Tests if a provided class member function pointer instance (not type!) is indeed an instance member m...
TFunction_Return< Function > InvokeWithTuple_Impl(Function &&function, TFunction_Arguments< Function > const &arguments, std::index_sequence< Sequence... > &&)
Return(typename TTupleElement< Indices, Tuple >::Type...) TFunctionFromTupleIndices
typename TFunctionTraits< std::decay_t< T > >::template Arg< I > TFunction_Arg
Shorthand for getting a type of a function argument at given position I.
typename TFunctionTraits< std::decay_t< T > >::Return TFunction_Return
Shorthand for getting a function return type.
typename TFunctionTraits< std::decay_t< T > >::Return TFunction_ReturnDecay
Shorthand for getting a function return type discarding qualifiers.
constexpr size_t TFunction_ArgCount
Shorthand for getting a function argument count.
TFunction_Return< Function > InvokeWithTuple(Function &&function, TFunction_Arguments< Function > const &arguments)
A clone of std::apply for Unreal tuples which also supports function pointers. TL;DR: It calls a func...
typename TFunctionTraits< std::decay_t< T > >::Class TFunction_Class
Shorthand for getting the class of a member function.
typename TFunctionTraits< std::decay_t< T > >::ArgumentsDecay TFunction_ArgumentsDecay
Shorthand for getting a tuple representing the decayed function arguments.
typename TFunctionTraits< std::decay_t< T > >::Signature TFunction_Signature
Shorthand for getting a pur function signature.
typename TFunctionTraits< std::decay_t< T > >::template ArgDecay< I > TFunction_ArgDecay
Shorthand for getting a decayed type of a function argument at given position I.
TSetReturn< TFunction_Return< SrcFunction >, DstFunction > TCopyReturn
Copy the return type from source function signature to the destination one.
TFunctionFromTuple< std::decay_t< Return >, TFunction_Arguments< DstFunction > > TSetReturnDecay
Override the return type of an input function signature, and discard its qualifiers.
TFunctionFromTuple< Return, TFunction_Arguments< DstFunction > > TSetReturn
Override the return type of an input function signature.
TSetReturnDecay< TFunction_ReturnDecay< SrcFunction >, DstFunction > TCopyReturnDecay
Copy the return type from source function signature to the destination one, and discard its qualifier...
typename Detail::TFunctionFromTuple_Struct< Return, std::decay_t< Tuple > >::Type TFunctionFromTuple
Compose a function type from a tuple of arguments and a return type.
typename TFunctionTraits< std::decay_t< T > >::Arguments TFunction_Arguments
Shorthand for getting a tuple representing the function arguments.
Templating utilities for manipulating TTuples.
Definition Tuples.h:23
typename TSkip_Struct< Count, Tuple >::Type TSkip
Skip the first Count elements of the input tuple.
Definition Tuples.h:177
static consteval TFunctionFromTupleIndices< Return, Tuple, Indices... > * Compose(std::index_sequence< Indices... > &&)
std::remove_pointer_t< decltype( Compose(std::make_index_sequence< TTupleArity< Tuple >::Value >{}))> Type
typename TTupleElement< I, ArgumentsDecay >::Type ArgDecay
TTuple< typename TDecay< Args >::Type... > ArgumentsDecay
typename TTupleElement< I, Arguments >::Type Arg
Defers a set of arguments for a function call later with its first argument. This is useful for devel...
TSkip< 1, TFunction_Arguments< Function > > ExtraArgs
Get signature information about any function declaring type (function pointer or functor structs incl...
static constexpr size_t ArgumentCount