MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
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 "Mcro/Tuples.h"
18#include "Mcro/Concepts.h"
19
21{
22 using namespace Mcro::Concepts;
23 using namespace Mcro::Tuples;
24
25 /** @brief Concept constraining input T to a lambda function or a functor object. */
26 template <typename T>
27 concept CFunctorObject = requires { &std::decay_t<T>::operator(); };
28
29 namespace Detail
30 {
31 template <typename ReturnIn, typename... Args>
33 {
34 static constexpr size_t ArgumentCount = sizeof...(Args);
35
36 using Return = ReturnIn;
37 using ReturnDecay = std::decay_t<ReturnIn>;
38
39 /** The input parameters of the function as a tuple type. Types are not decayed. */
40 using Arguments = TTuple<Args...>;
41
42 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
43 using ArgumentsDecay = TTuple<std::decay_t<Args>...>;
44
45 /** The input parameters of the function as a std::tuple type. Types are not decayed. */
46 using ArgumentsStd = std::tuple<Args...>;
47
48 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
49 using ArgumentsStdDecay = std::tuple<std::decay_t<Args>...>;
50
51 /** The input parameters of the function as a std::tuple type. Types are not decayed. */
52 using ArgumentsRangeV3 = ranges::common_tuple<Args...>;
53
54 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
55 using ArgumentsRangeV3Decay = ranges::common_tuple<std::decay_t<Args>...>;
56
57 /** The pure function signature with other information stripped from it */
58 using Signature = Return(Args...);
59
60 template <int I>
62
63 template <int I>
65 };
66 }
67
68 /**
69 * @brief
70 * Get signature information about any function declaring type (function pointer or functor
71 * structs including lambda functions). It should be used in other templates.
72 *
73 * @tparam T the inferred type of the input function. 99% of cases this should be inferred.
74 */
75 template <typename T>
77 {
78 static constexpr size_t ArgumentCount = 0;
79 static constexpr bool IsFunction = false;
80 static constexpr bool IsPointer = false;
81 static constexpr bool IsFunctor = false;
82 static constexpr bool IsMember = false;
83 static constexpr bool IsConst = false;
84 };
85
86 /** @brief Specialization for functor structs / lambda functions. */
87 template <CFunctorObject T>
88 struct TFunctionTraits<T> : TFunctionTraits<decltype(&std::decay_t<T>::operator())>
89 {
90 static constexpr bool IsFunction = true;
91 static constexpr bool IsPointer = false;
92 static constexpr bool IsFunctor = true;
93 static constexpr bool IsMember = false;
94 static constexpr bool IsConst = false;
95 };
96
97 /** @brief Specialization extracting the types from the compound function pointer type of a const member function. */
98 template <typename ClassIn, typename ReturnIn, typename... Args>
99 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...) const> : Detail::TFunctionMeta<ReturnIn, Args...>
100 {
101 using Class = ClassIn;
102 static constexpr bool IsFunction = true;
103 static constexpr bool IsPointer = true;
104 static constexpr bool IsFunctor = false;
105 static constexpr bool IsMember = true;
106 static constexpr bool IsConst = true;
107 };
108
109 /** @brief Specialization extracting the types from the compound function pointer type of a member function. */
110 template <typename ClassIn, typename ReturnIn, typename... Args>
111 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
112 {
113 using Class = ClassIn;
114 static constexpr bool IsFunction = true;
115 static constexpr bool IsPointer = true;
116 static constexpr bool IsFunctor = false;
117 static constexpr bool IsMember = true;
118 static constexpr bool IsConst = false;
119 };
120
121 /** @brief Specialization extracting the types from the compound function pointer 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 = true;
127 static constexpr bool IsFunctor = false;
128 static constexpr bool IsMember = false;
129 static constexpr bool IsConst = false;
130 };
131
132 /** @brief Specialization extracting the types from the compound function type. */
133 template <typename ReturnIn, typename... Args>
134 struct TFunctionTraits<ReturnIn(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
135 {
136 static constexpr bool IsFunction = true;
137 static constexpr bool IsPointer = false;
138 static constexpr bool IsFunctor = false;
139 static constexpr bool IsMember = false;
140 static constexpr bool IsConst = false;
141 };
142
143 /** @brief Shorthand for getting a tuple representing the function arguments. */
144 template <typename T>
146
147 /** @brief Shorthand for getting a tuple representing the decayed function arguments. */
148 template <typename T>
150
151 /** @brief Shorthand for getting a type of a function argument at given position I. */
152 template <typename T, int I>
153 using TFunction_Arg = typename TFunctionTraits<std::decay_t<T>>::template Arg<I>;
154
155 /** @brief Shorthand for getting a decayed type of a function argument at given position I. */
156 template <typename T, int I>
157 using TFunction_ArgDecay = typename TFunctionTraits<std::decay_t<T>>::template ArgDecay<I>;
158
159 /** @brief Shorthand for getting a function argument count. */
160 template <typename T>
161 inline constexpr size_t TFunction_ArgCount = TFunctionTraits<std::decay_t<T>>::ArgumentCount;
162
163 /** @brief Shorthand for getting a function return type. */
164 template <typename T>
166
167 /** @brief Shorthand for getting a function return type discarding qualifiers. */
168 template <typename T>
170
171 /** @brief Shorthand for getting a pur function signature. */
172 template <typename T>
174
175 template <typename T>
176 concept CFunction_IsMember = TFunctionTraits<std::decay_t<T>>::IsMember;
177
178 /** @brief Shorthand for getting the class of a member function. */
179 template <CFunction_IsMember T>
181
182 /** @brief Shorthand for getting the constness of a member function. */
183 template <typename T>
184 concept CFunction_IsConst = TFunctionTraits<std::decay_t<T>>::IsConst;
185
186 /** @brief A concept accepting any function like entity (function pointer or functor object) */
187 template <typename T>
188 concept CFunctionLike = TFunctionTraits<std::decay_t<T>>::IsFunction;
189
190 /** @brief A concept accepting function pointer types */
191 template <typename T>
192 concept CFunctionPtr = TFunctionTraits<std::decay_t<T>>::IsPointer;
193
194 template <typename Class, typename Function>
196 && (CDerivedFrom<Class, TFunction_Class<Function>> || CSameAs<Class, TFunction_Class<Function>>)
197 ;
198
199 namespace Detail
200 {
201 template <typename Return, typename Tuple, size_t... Indices>
202 using TFunctionFromTupleIndices = Return(typename TTupleElement<Indices, Tuple>::Type...);
203
204 template <typename Return, typename Tuple>
206 {
207 template <size_t... Indices>
208 static consteval TFunctionFromTupleIndices<Return, Tuple, Indices...>* Compose(std::index_sequence<Indices...>&&);
209
210 using Type = std::remove_pointer_t<decltype(
211 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value>{})
212 )>;
213 };
214 }
215
216 /** @brief Compose a function type from a tuple of arguments and a return type */
217 template <typename Return, typename Tuple>
219
220 /** @brief Override the return type of an input function signature */
221 template <typename Return, typename DstFunction>
223
224 /** @brief Override the return type of an input function signature, and discard its qualifiers */
225 template <typename Return, typename DstFunction>
227
228 /** @brief Copy the return type from source function signature to the destination one */
229 template <typename SrcFunction, typename DstFunction>
231
232 /** @brief Copy the return type from source function signature to the destination one, and discard its qualifiers */
233 template <typename SrcFunction, typename DstFunction>
235
236 namespace Detail
237 {
238 template <typename Function, CTuple Tuple, size_t... Sequence>
240 Function&& function,
241 Tuple&& arguments,
242 std::index_sequence<Sequence...>&&
243 ) {
244 return function(GetItem<Sequence>(arguments)...);
245 }
246
247 template <typename Object, typename Function, CTuple Tuple, size_t... Sequence>
249 Object* object,
250 Function&& function,
251 Tuple&& arguments,
252 std::index_sequence<Sequence...>&&
253 ) {
254 return (object->*function)(GetItem<Sequence>(arguments)...);
255 }
256 }
257
258 /**
259 * @brief Is given tuple type compatible with the arguments of the given function?
260 *
261 * Works with `TTuple`, `std::tuple` and `ranges::common_tuple` (tuple type of RangeV3 library)
262 */
263 template <typename Tuple, typename Function>
265 CTuple<Tuple> && CFunctionLike<Function>
266 && (
267 CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::Arguments>
268 || CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::ArgumentsStd>
269 || CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::ArgumentsRangeV3>
270 )
271 ;
272
273 /**
274 * @brief
275 * A clone of std::apply for Unreal, STL and RangeV3 tuples which also supports function pointers.
276 *
277 * TL;DR: It calls a function with arguments supplied from a tuple.
278 */
279 template <typename Function, CTupleCompatibleWithFunction<Function> Tuple>
280 TFunction_Return<Function> InvokeWithTuple(Function&& function, Tuple&& arguments)
281 {
283 FWD(function), FWD(arguments),
284 std::make_index_sequence<TFunction_ArgCount<Function>>()
285 );
286 }
287
288 /**
289 * @brief
290 * A clone of std::apply for Unreal, STL and RangeV3 tuples which also supports function pointers. This overload
291 * can bind an object
292 *
293 * TL;DR: It calls a function with arguments supplied from a tuple.
294 */
295 template <
296 CFunctionPtr Function,
297 CHasFunction<Function> Object,
298 CTupleCompatibleWithFunction<Function> Tuple
299 >
300 TFunction_Return<Function> InvokeWithTuple(Object* object, Function&& function, Tuple&& arguments)
301 {
303 object,
304 FWD(function), FWD(arguments),
305 std::make_index_sequence<TFunction_ArgCount<Function>>()
306 );
307 }
308
309 /** @brief Concept matching the return of a type with compatible return types, disregarding CV-ref qualifiers. */
310 template <typename F, typename Return>
313 && CConvertibleToDecayed<TFunction_ReturnDecay<F>, Return>
314 ;
315
316 /** @brief Concept matching the return of a type with compatible return types, preserving CV-ref qualifiers. */
317 template <typename F, typename Return>
320 && CConvertibleTo<TFunction_Return<F>, Return>
321 ;
322
323 /** @brief Concept matching function types with compatible set of arguments, disregarding CV-ref qualifiers. */
324 template <typename F, typename With>
328 && CConvertibleToDecayed<
331 >
332 ;
333
334 /** @brief Concept matching function types with compatible set of arguments, preserving CV-ref qualifiers. */
335 template <typename F, typename With>
339 && CConvertibleTo<
342 >
343 ;
344
345 /**
346 * @brief
347 * Concept constraining a function type to another one which arguments and return types are compatible,
348 * disregarding CV-ref qualifiers
349 */
350 template <typename F, typename With>
356 ;
357
358 /**
359 * @brief
360 * Concept constraining a function type to another one which arguments and return types are compatible,
361 * preserving CV-ref qualifiers
362 */
363 template <typename F, typename With>
369 ;
370
371 /** @brief Concept matching function types returning void. */
372 template <typename F>
373 concept CFunctionReturnsVoid = CFunctionLike<F> && std::is_void_v<TFunction_Return<F>>;
374
375 /**
376 * @brief
377 * Tests if a provided class member function pointer instance (not type!) is indeed an instance member method.
378 * Negating it can assume static class member function
379 */
380 template <auto FuncPtr>
381 concept CInstanceMethod = requires(
382 TFunction_Class<decltype(FuncPtr)>* instance,
383 TFunction_Arguments<decltype(FuncPtr)> argsTuple
384 ) {
385 InvokeWithTuple(instance, FuncPtr, argsTuple);
386 };
387
388 /**
389 * @brief
390 * Defers a set of arguments for a function call later with its first argument. This is useful for developing
391 * fluent API operators.
392 */
393 template <auto FuncPtr, CFunctionPtr Function = decltype(FuncPtr)>
394 requires (
395 CFunctionPtr<decltype(FuncPtr)>
396 && TFunction_ArgCount<decltype(FuncPtr)> > 0
397 )
399 {
403
404 template <typename... Args>
406 : Storage(FWD(args)...)
407 {}
408
409 template <CConvertibleToDecayed<FirstArg> FirstArgRef>
410 Return operator () (FirstArgRef&& arg)
411 {
412 auto args = arg >> Storage;
413 return InvokeWithTuple<Function>(FuncPtr, args);
414 }
415
416 private:
417 ExtraArgs Storage;
418 };
419}
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
Concept constraining a function type to another one which arguments and return types are compatible,...
Concept matching function types with compatible set of arguments, disregarding CV-ref qualifiers.
Concept matching function types with compatible set of arguments, preserving CV-ref qualifiers.
Concept matching the return of a type with compatible return types, disregarding CV-ref qualifiers.
Concept matching the return of a type with compatible return types, preserving CV-ref qualifiers.
Concept constraining a function type to another one which arguments and return types are compatible,...
A concept accepting any function like entity (function pointer or functor object)
A concept accepting function pointer types.
Concept matching function types returning void.
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...
Is given tuple type compatible with the arguments of the given function?
Return(typename TTupleElement< Indices, Tuple >::Type...) TFunctionFromTupleIndices
TFunction_Return< Function > InvokeWithTuple_Impl(Function &&function, Tuple &&arguments, std::index_sequence< Sequence... > &&)
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.
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.
TFunction_Return< Function > InvokeWithTuple(Function &&function, Tuple &&arguments)
A clone of std::apply for Unreal, STL and RangeV3 tuples which also supports function pointers.
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:24
typename TSkip_Struct< Count, Tuple >::Type TSkip
Skip the first Count elements of the input tuple.
Definition Tuples.h:179
typename TTypeAt_Struct< I, T >::Type TTypeAt
Definition Tuples.h:154
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
TTuple< std::decay_t< Args >... > ArgumentsDecay
ranges::common_tuple< Args... > ArgumentsRangeV3
std::tuple< std::decay_t< Args >... > ArgumentsStdDecay
ranges::common_tuple< std::decay_t< Args >... > ArgumentsRangeV3Decay
TTypeAt< I, ArgumentsDecay > ArgDecay
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