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 = TTypes<Args...>;
41
42 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
44
45 /** The input parameters of the function as a tuple type. Types are not decayed. */
46 using ArgumentsTuple = TTuple<Args...>;
47
48 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
49 using ArgumentsTupleDecay = TTuple<std::decay_t<Args>...>;
50
51 /** The input parameters of the function as a std::tuple type. Types are not decayed. */
52 using ArgumentsStd = std::tuple<Args...>;
53
54 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
55 using ArgumentsStdDecay = std::tuple<std::decay_t<Args>...>;
56
57 /** The input parameters of the function as a std::tuple type. Types are not decayed. */
58 using ArgumentsRangeV3 = ranges::common_tuple<Args...>;
59
60 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
61 using ArgumentsRangeV3Decay = ranges::common_tuple<std::decay_t<Args>...>;
62
63 /** The pure function signature with other information stripped from it */
64 using Signature = Return(Args...);
65
66 template <int I>
68
69 template <int I>
71 };
72 }
73
74 /**
75 * @brief
76 * Get signature information about any function declaring type (function pointer or functor
77 * structs including lambda functions). It should be used in other templates.
78 *
79 * @tparam T the inferred type of the input function. 99% of cases this should be inferred.
80 */
81 template <typename T>
83 {
84 static constexpr size_t ArgumentCount = 0;
85 static constexpr bool IsFunction = false;
86 static constexpr bool IsPointer = false;
87 static constexpr bool IsFunctor = false;
88 static constexpr bool IsMember = false;
89 static constexpr bool IsConst = false;
90 };
91
92 /** @brief Specialization for functor structs / lambda functions. */
93 template <CFunctorObject T>
94 struct TFunctionTraits<T> : TFunctionTraits<decltype(&std::decay_t<T>::operator())>
95 {
96 static constexpr bool IsFunction = true;
97 static constexpr bool IsPointer = false;
98 static constexpr bool IsFunctor = true;
99 static constexpr bool IsMember = false;
100 static constexpr bool IsConst = false;
101 };
102
103 /** @brief Specialization extracting the types from the compound function pointer type of a const member function. */
104 template <typename ClassIn, typename ReturnIn, typename... Args>
105 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...) const> : Detail::TFunctionMeta<ReturnIn, Args...>
106 {
107 using Class = ClassIn;
108 static constexpr bool IsFunction = true;
109 static constexpr bool IsPointer = true;
110 static constexpr bool IsFunctor = false;
111 static constexpr bool IsMember = true;
112 static constexpr bool IsConst = true;
113 };
114
115 /** @brief Specialization extracting the types from the compound function pointer type of a member function. */
116 template <typename ClassIn, typename ReturnIn, typename... Args>
117 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
118 {
119 using Class = ClassIn;
120 static constexpr bool IsFunction = true;
121 static constexpr bool IsPointer = true;
122 static constexpr bool IsFunctor = false;
123 static constexpr bool IsMember = true;
124 static constexpr bool IsConst = false;
125 };
126
127 /** @brief Specialization extracting the types from the compound function pointer type. */
128 template <typename ReturnIn, typename... Args>
129 struct TFunctionTraits<ReturnIn(*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
130 {
131 static constexpr bool IsFunction = true;
132 static constexpr bool IsPointer = true;
133 static constexpr bool IsFunctor = false;
134 static constexpr bool IsMember = false;
135 static constexpr bool IsConst = false;
136 };
137
138 /** @brief Specialization extracting the types from the compound function type. */
139 template <typename ReturnIn, typename... Args>
140 struct TFunctionTraits<ReturnIn(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
141 {
142 static constexpr bool IsFunction = true;
143 static constexpr bool IsPointer = false;
144 static constexpr bool IsFunctor = false;
145 static constexpr bool IsMember = false;
146 static constexpr bool IsConst = false;
147 };
148
149 /** @brief Shorthand for getting a list representing the function arguments. */
150 template <typename T>
152
153 /** @brief Shorthand for getting a list representing the decayed function arguments. */
154 template <typename T>
156
157 /** @brief Shorthand for getting a list representing the function arguments. */
158 template <typename T>
160
161 /** @brief Shorthand for getting a list representing the decayed function arguments. */
162 template <typename T>
164
165 /** @brief Shorthand for getting a list representing the function arguments. */
166 template <typename T>
168
169 /** @brief Shorthand for getting a list representing the decayed function arguments. */
170 template <typename T>
172
173 /** @brief Shorthand for getting a list representing the function arguments. */
174 template <typename T>
176
177 /** @brief Shorthand for getting a list representing the decayed function arguments. */
178 template <typename T>
179 using TFunction_ArgumentsRangeV3Decay = typename TFunctionTraits<std::decay_t<T>>::ArgumentsRangeV3Decay;
180
181 /** @brief Shorthand for getting a type of a function argument at given position I. */
182 template <typename T, int I>
183 using TFunction_Arg = typename TFunctionTraits<std::decay_t<T>>::template Arg<I>;
184
185 /** @brief Shorthand for getting a decayed type of a function argument at given position I. */
186 template <typename T, int I>
187 using TFunction_ArgDecay = typename TFunctionTraits<std::decay_t<T>>::template ArgDecay<I>;
188
189 /** @brief Shorthand for getting a function argument count. */
190 template <typename T>
191 inline constexpr size_t TFunction_ArgCount = TFunctionTraits<std::decay_t<T>>::ArgumentCount;
192
193 /** @brief Shorthand for getting a function return type. */
194 template <typename T>
196
197 /** @brief Shorthand for getting a function return type discarding qualifiers. */
198 template <typename T>
200
201 /** @brief Shorthand for getting a pur function signature. */
202 template <typename T>
204
205 template <typename T>
206 concept CFunction_IsMember = TFunctionTraits<std::decay_t<T>>::IsMember;
207
208 /** @brief Shorthand for getting the class of a member function. */
209 template <CFunction_IsMember T>
211
212 /** @brief Shorthand for getting the constness of a member function. */
213 template <typename T>
214 concept CFunction_IsConst = TFunctionTraits<std::decay_t<T>>::IsConst;
215
216 /** @brief A concept accepting any function like entity (function pointer or functor object) */
217 template <typename T>
218 concept CFunctionLike = TFunctionTraits<std::decay_t<T>>::IsFunction;
219
220 /** @brief A concept accepting function pointer types */
221 template <typename T>
222 concept CFunctionPtr = TFunctionTraits<std::decay_t<T>>::IsPointer;
223
224 template <typename Class, typename Function>
226 && (CDerivedFrom<Class, TFunction_Class<Function>> || CSameAs<Class, TFunction_Class<Function>>)
227 ;
228
229 namespace Detail
230 {
231 template <typename Return, typename>
233 {
234 using Type = void;
235 };
236
237 template <typename Return, typename... Types>
238 struct TFunctionFromTypes_Struct<Return, TTypes<Types...>>
239 {
240 using Type = Return(Types...);
241 };
242 }
243
244 /** @brief Compose a function type from a tuple of arguments and a return type */
245 template <typename Return, typename TypeList>
247
248 /** @brief Override the return type of an input function signature */
249 template <typename Return, typename DstFunction>
251
252 /** @brief Override the return type of an input function signature, and discard its qualifiers */
253 template <typename Return, typename DstFunction>
255
256 /** @brief Copy the return type from source function signature to the destination one */
257 template <typename SrcFunction, typename DstFunction>
259
260 /** @brief Copy the return type from source function signature to the destination one, and discard its qualifiers */
261 template <typename SrcFunction, typename DstFunction>
263
264 namespace Detail
265 {
266 template <typename Function, CTuple Tuple, size_t... Sequence>
268 Function&& function,
269 Tuple&& arguments,
270 std::index_sequence<Sequence...>&&
271 ) {
272 return function(GetItem<Sequence>(arguments)...);
273 }
274
275 template <typename Object, typename Function, CTuple Tuple, size_t... Sequence>
277 Object* object,
278 Function&& function,
279 Tuple&& arguments,
280 std::index_sequence<Sequence...>&&
281 ) {
282 return (object->*function)(GetItem<Sequence>(arguments)...);
283 }
284 }
285
286 /**
287 * @brief Is given tuple type compatible with the arguments of the given function?
288 *
289 * Works with `TTuple`, `std::tuple` and `ranges::common_tuple` (tuple type of RangeV3 library)
290 */
291 template <typename Tuple, typename Function>
293 CTuple<Tuple> && CFunctionLike<Function>
294 && (
295 CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::ArgumentsTuple>
296 || CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::ArgumentsStd>
297 || CConvertibleTo<Tuple, typename TFunctionTraits<std::decay_t<Function>>::ArgumentsRangeV3>
298 )
299 ;
300
301 /**
302 * @brief
303 * A clone of std::apply for Unreal, STL and RangeV3 tuples which also supports function pointers.
304 *
305 * TL;DR: It calls a function with arguments supplied from a tuple.
306 */
307 template <typename Function, CTupleCompatibleWithFunction<Function> Tuple>
308 TFunction_Return<Function> InvokeWithTuple(Function&& function, Tuple&& arguments)
309 {
311 FWD(function), FWD(arguments),
312 std::make_index_sequence<TFunction_ArgCount<Function>>()
313 );
314 }
315
316 /**
317 * @brief
318 * A clone of std::apply for Unreal, STL and RangeV3 tuples which also supports function pointers. This overload
319 * can bind an object
320 *
321 * TL;DR: It calls a function with arguments supplied from a tuple.
322 */
323 template <
324 CFunctionPtr Function,
325 CHasFunction<Function> Object,
326 CTupleCompatibleWithFunction<Function> Tuple
327 >
328 TFunction_Return<Function> InvokeWithTuple(Object* object, Function&& function, Tuple&& arguments)
329 {
331 object,
332 FWD(function), FWD(arguments),
333 std::make_index_sequence<TFunction_ArgCount<Function>>()
334 );
335 }
336
337 /** @brief Concept matching the return of a type with compatible return types, disregarding CV-ref qualifiers. */
338 template <typename F, typename Return>
341 && CConvertibleToDecayed<TFunction_ReturnDecay<F>, Return>
342 ;
343
344 /** @brief Concept matching the return of a type with compatible return types, preserving CV-ref qualifiers. */
345 template <typename F, typename Return>
348 && CConvertibleTo<TFunction_Return<F>, Return>
349 ;
350
351 /** @brief Concept matching function types with compatible set of arguments, disregarding CV-ref qualifiers. */
352 template <typename F, typename With>
356 && CTypesConvertibleToDecayed<
359 >
360 ;
361
362 /** @brief Concept matching function types with compatible set of arguments, preserving CV-ref qualifiers. */
363 template <typename F, typename With>
367 && CTypesConvertibleTo<
370 >
371 ;
372
373 /**
374 * @brief
375 * Concept constraining a function type to another one which arguments and return types are compatible,
376 * disregarding CV-ref qualifiers
377 */
378 template <typename F, typename With>
384 ;
385
386 /**
387 * @brief
388 * Concept constraining a function type to another one which arguments and return types are compatible,
389 * preserving CV-ref qualifiers
390 */
391 template <typename F, typename With>
397 ;
398
399 /** @brief Accept only functions which has given number of arguments, whatever type they may be */
400 template <typename Function, size_t Count>
403 ;
404
405 /** @brief Accept only functions which has 0 arguments */
406 template <typename Function>
408
409 /** @brief Concept matching function types returning void. */
410 template <typename F>
411 concept CFunctionReturnsVoid = CFunctionLike<F> && std::is_void_v<TFunction_Return<F>>;
412
413 /**
414 * @brief
415 * Tests if a provided class member function pointer instance (not type!) is indeed an instance member method.
416 * Negating it can assume static class member function
417 */
418 template <auto FuncPtr>
419 concept CInstanceMethod = requires(
420 TFunction_Class<decltype(FuncPtr)>* instance,
421 TFunction_ArgumentsTuple<decltype(FuncPtr)> argsTuple
422 ) {
423 InvokeWithTuple(instance, FuncPtr, argsTuple);
424 };
425
426 /**
427 * @brief
428 * Defers a set of arguments for a function call later with its first argument. This is useful for developing
429 * fluent API operators.
430 */
431 template <auto FuncPtr, CFunctionPtr Function = decltype(FuncPtr)>
432 requires (
433 CFunctionPtr<decltype(FuncPtr)>
434 && TFunction_ArgCount<decltype(FuncPtr)> > 0
435 )
437 {
441
442 template <typename... Args>
444 : Storage(FWD(args)...)
445 {}
446
447 template <CConvertibleToDecayed<FirstArg> FirstArgRef>
448 Return operator () (FirstArgRef&& arg)
449 {
450 auto args = arg >> Storage;
451 return InvokeWithTuple<Function>(FuncPtr, args);
452 }
453
454 private:
455 ExtraArgs Storage;
456 };
457}
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.
Accept only functions which has given number of arguments, whatever type they may be.
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...
Accept only functions which has 0 arguments.
Is given tuple type compatible with the arguments of the given function?
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 > >::ArgumentsStd TFunction_ArgumentsStd
Shorthand for getting a list representing the function arguments.
typename TFunctionTraits< std::decay_t< T > >::ArgumentsTupleDecay TFunction_ArgumentsTupleDecay
Shorthand for getting a list representing the decayed function arguments.
typename Detail::TFunctionFromTypes_Struct< Return, std::decay_t< TypeList > >::Type TFunctionFromTypes
Compose a function type from a tuple of arguments and a return type.
typename TFunctionTraits< std::decay_t< T > >::ArgumentsStdDecay TFunction_ArgumentsStdDecay
Shorthand for getting a list representing the decayed function arguments.
TFunctionFromTypes< Return, TFunction_Arguments< DstFunction > > TSetReturn
Override the return type of an input function signature.
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 > >::ArgumentsRangeV3 TFunction_ArgumentsRangeV3
Shorthand for getting a list representing the function arguments.
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 list 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.
TSetReturnDecay< TFunction_ReturnDecay< SrcFunction >, DstFunction > TCopyReturnDecay
Copy the return type from source function signature to the destination one, and discard its qualifier...
TFunctionFromTypes< std::decay_t< Return >, TFunction_Arguments< DstFunction > > TSetReturnDecay
Override the return type of an input function signature, and discard its qualifiers.
typename TFunctionTraits< std::decay_t< T > >::ArgumentsRangeV3Decay TFunction_ArgumentsRangeV3Decay
Shorthand for getting a list representing the decayed function arguments.
typename TFunctionTraits< std::decay_t< T > >::Arguments TFunction_Arguments
Shorthand for getting a list representing the function arguments.
typename TFunctionTraits< std::decay_t< T > >::ArgumentsTuple TFunction_ArgumentsTuple
Shorthand for getting a list representing the function arguments.
T::template Get< I > TTypes_Get
Definition Templates.h:128
Templating utilities for manipulating TTuples.
Definition Tuples.h:24
typename TTupleSkip_Struct< Count, Tuple >::Type TTupleSkip
Skip the first Count elements of the input tuple.
Definition Tuples.h:179
ranges::common_tuple< Args... > ArgumentsRangeV3
std::tuple< std::decay_t< Args >... > ArgumentsStdDecay
ranges::common_tuple< std::decay_t< Args >... > ArgumentsRangeV3Decay
TTuple< std::decay_t< Args >... > ArgumentsTupleDecay
TTypes_Get< ArgumentsDecay, I > ArgDecay
Defers a set of arguments for a function call later with its first argument. This is useful for devel...
TTupleSkip< 1, TFunction_ArgumentsTuple< Function > > ExtraArgs
Get signature information about any function declaring type (function pointer or functor structs incl...
static constexpr size_t ArgumentCount
This template is used to store pack of types in other templates, or to allow parameter pack inference...
Definition Templates.h:107