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/Concepts.h"
18
20{
21 using namespace Mcro::Concepts;
22
23 /** Concept constraining input T to a lambda function or a functor object. */
24 template <typename T>
25 concept CFunctorObject = requires { &std::decay_t<T>::operator(); };
26
27 namespace Detail
28 {
29 template <typename ReturnIn, typename... Args>
31 {
32 static constexpr size_t ArgumentCount = sizeof...(Args);
33
34 using Return = ReturnIn;
35
36 /** The input parameters of the function as a tuple type. Types are not decayed. */
37 using Arguments = TTuple<Args...>;
38
39 /** The input parameters of the function as a tuple type. Types are decayed (useful for storage) */
40 using ArgumentsDecay = TTuple<typename TDecay<Args>::Type...>;
41
42 /** The pure function signature with other information stripped from it */
43 using Signature = Return(Args...);
44
45 template <int I>
46 using Arg = typename TTupleElement<I, Arguments>::Type;
47
48 template <int I>
49 using ArgDecay = typename TTupleElement<I, ArgumentsDecay>::Type;
50 };
51 }
52
53 /**
54 * Get signature information about any function declaring type (function pointer or functor
55 * structs including lambda functions). It should be used in other templates.
56 *
57 * @tparam T the inferred type of the input function. 99% of cases this should be inferred.
58 */
59 template <typename T>
61 {
62 static constexpr size_t ArgumentCount = 0;
63 static constexpr bool IsFunction = false;
64 static constexpr bool IsPointer = false;
65 static constexpr bool IsFunctor = false;
66 static constexpr bool IsMember = false;
67 static constexpr bool IsConst = false;
68 };
69
70 /** Specialization for functor structs / lambda functions. */
71 template <CFunctorObject T>
72 struct TFunctionTraits<T> : TFunctionTraits<decltype(&std::decay_t<T>::operator())>
73 {
74 static constexpr bool IsFunction = true;
75 static constexpr bool IsPointer = false;
76 static constexpr bool IsFunctor = true;
77 static constexpr bool IsMember = false;
78 static constexpr bool IsConst = false;
79 };
80
81 /** Specialization extracting the types from the compound function pointer type of a const member function. */
82 template <typename ClassIn, typename ReturnIn, typename... Args>
83 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...) const> : Detail::TFunctionMeta<ReturnIn, Args...>
84 {
85 using Class = ClassIn;
86 static constexpr bool IsFunction = true;
87 static constexpr bool IsPointer = true;
88 static constexpr bool IsFunctor = false;
89 static constexpr bool IsMember = true;
90 static constexpr bool IsConst = true;
91 };
92
93 /** Specialization extracting the types from the compound function pointer type of a member function. */
94 template <typename ClassIn, typename ReturnIn, typename... Args>
95 struct TFunctionTraits<ReturnIn(ClassIn::*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
96 {
97 using Class = ClassIn;
98 static constexpr bool IsFunction = true;
99 static constexpr bool IsPointer = true;
100 static constexpr bool IsFunctor = false;
101 static constexpr bool IsMember = true;
102 static constexpr bool IsConst = false;
103 };
104
105 /** Specialization extracting the types from the compound function pointer type. */
106 template <typename ReturnIn, typename... Args>
107 struct TFunctionTraits<ReturnIn(*)(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
108 {
109 static constexpr bool IsFunction = true;
110 static constexpr bool IsPointer = true;
111 static constexpr bool IsFunctor = false;
112 static constexpr bool IsMember = false;
113 static constexpr bool IsConst = false;
114 };
115
116 /** Specialization extracting the types from the compound function type. */
117 template <typename ReturnIn, typename... Args>
118 struct TFunctionTraits<ReturnIn(Args...)> : Detail::TFunctionMeta<ReturnIn, Args...>
119 {
120 static constexpr bool IsFunction = true;
121 static constexpr bool IsPointer = false;
122 static constexpr bool IsFunctor = false;
123 static constexpr bool IsMember = false;
124 static constexpr bool IsConst = false;
125 };
126
127
128 /** Shorthand for getting a type of a function argument at given position I. */
129 template <typename T>
131
132 /** Shorthand for getting a type of a function argument at given position I. */
133 template <typename T, int I>
134 using TFunction_Arg = typename TFunctionTraits<std::decay_t<T>>::template Arg<I>;
135
136 /** Shorthand for getting a decayed type of a function argument at given position I. */
137 template <typename T, int I>
138 using TFunction_ArgDecay = typename TFunctionTraits<std::decay_t<T>>::template ArgDecay<I>;
139
140 template <typename T>
141 inline constexpr size_t TFunction_ArgCount = TFunctionTraits<std::decay_t<T>>::ArgumentCount;
142
143 template <typename T>
145
146 template <typename T>
148
149 template <typename T>
151
152 template <typename T>
153 inline constexpr bool TFunction_IsMember = TFunctionTraits<std::decay_t<T>>::IsMember;
154
155 template <typename T>
156 inline constexpr bool TFunction_IsConst = TFunctionTraits<std::decay_t<T>>::IsConst;
157
158 /** A concept accepting any function like entity (function pointer or functor object) */
159 template <typename T>
160 concept CFunctionLike = TFunctionTraits<std::decay_t<T>>::IsFunction;
161
162 template <typename T>
163 concept CFunctionPtr = TFunctionTraits<std::decay_t<T>>::IsPointer;
164
165 template <typename Class, typename Function>
167 && (CDerivedFrom<Class, TFunction_Class<Function>> || CSameAs<Class, TFunction_Class<Function>>)
168 ;
169
170 template <typename Return, typename Tuple, size_t... Indices>
171 using TFunctionFromTupleIndices = Return(typename TTupleElement<Indices, Tuple>::Type...);
172
173 template <typename Return, typename Tuple>
175 {
176 template <size_t... Indices>
177 static consteval TFunctionFromTupleIndices<Return, Tuple, Indices...>* Compose(std::index_sequence<Indices...>&&);
178
179 using Type = std::remove_pointer_t<decltype(
180 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value>{})
181 )>;
182 };
183
184 template <typename Return, typename Tuple>
185 using TFunctionFromTuple = typename TFunctionFromTuple_Struct<std::decay_t<Return>, std::decay_t<Tuple>>::Type;
186
187 template <typename Return, typename DstFunction>
189
190 template <typename SrcFunction, typename DstFunction>
192
193 namespace Detail
194 {
195 template<typename Function, size_t... Sequence>
197 Function&& function,
198 TFunction_Arguments<Function> const& arguments,
199 std::index_sequence<Sequence...>&&
200 )
201 {
202 return function(Forward<TFunction_Arg<Function, Sequence>>(arguments.template Get<Sequence>())...);
203 }
204
205 template<typename Object, typename Function, size_t... Sequence>
207 Object* object,
208 Function&& function,
209 TFunction_Arguments<Function> const& arguments,
210 std::index_sequence<Sequence...>&&
211 )
212 {
213 return (object->*function)(Forward<TFunction_Arg<Function, Sequence>>(arguments.template Get<Sequence>())...);
214 }
215 }
216
217 /**
218 * A clone of std::apply for Unreal tuples which also supports function pointers.
219 * TL;DR: It calls a function with arguments supplied from a tuple.
220 */
221 template<typename Function>
223 {
225 Forward<Function>(function), arguments,
226 std::make_index_sequence<TFunction_ArgCount<Function>>()
227 );
228 }
229
230 /**
231 * A clone of std::apply for Unreal tuples which also supports function pointers. This overload can bind an object
232 * TL;DR: It calls a function with arguments supplied from a tuple.
233 */
234 template<CFunctionPtr Function, CHasFunction<Function> Object>
235 TFunction_Return<Function> InvokeWithTuple(Object* object, Function&& function, TFunction_Arguments<Function> const& arguments)
236 {
238 object,
239 Forward<Function>(function), arguments,
240 std::make_index_sequence<TFunction_ArgCount<Function>>()
241 );
242 }
243}
TFunction_Return< Function > InvokeWithTuple_Impl(Function &&function, TFunction_Arguments< Function > const &arguments, std::index_sequence< Sequence... > &&)
typename TFunctionTraits< std::decay_t< T > >::template Arg< I > TFunction_Arg
constexpr bool TFunction_IsConst
typename TFunctionTraits< std::decay_t< T > >::Return TFunction_Return
constexpr size_t TFunction_ArgCount
TFunction_Return< Function > InvokeWithTuple(Function &&function, TFunction_Arguments< Function > const &arguments)
typename TFunctionFromTuple_Struct< std::decay_t< Return >, std::decay_t< Tuple > >::Type TFunctionFromTuple
typename TFunctionTraits< std::decay_t< T > >::Class TFunction_Class
typename TFunctionTraits< std::decay_t< T > >::Signature TFunction_Signature
typename TFunctionTraits< std::decay_t< T > >::template ArgDecay< I > TFunction_ArgDecay
Return(typename TTupleElement< Indices, Tuple >::Type...) TFunctionFromTupleIndices
TSetReturn< TFunction_Return< SrcFunction >, DstFunction > TCopyReturn
constexpr bool TFunction_IsMember
TFunctionFromTuple< Return, TFunction_Arguments< DstFunction > > TSetReturn
typename TFunctionTraits< std::decay_t< T > >::Arguments TFunction_Arguments
typename TTupleElement< I, ArgumentsDecay >::Type ArgDecay
TTuple< typename TDecay< Args >::Type... > ArgumentsDecay
typename TTupleElement< I, Arguments >::Type Arg
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
static constexpr size_t ArgumentCount