MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Macros.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 "CoreMinimal.h"
15#include "HAL/PreprocessorHelpers.h"
16#include "boost/preprocessor.hpp"
17#include "Misc/EngineVersionComparison.h"
18
19// These here are back-porting missing macros from UE 5.4 to at least UE 5.3
20#if UE_VERSION_OLDER_THAN(5, 4, 0)
21
22// Expands to a number which is the count of variadic arguments passed to it.
23#define UE_VA_ARG_COUNT(...) UE_APPEND_VA_ARG_COUNT(, ##__VA_ARGS__)
24
25// Expands to nothing when used as a function - used as a placeholder
26#define UE_EMPTY_FUNCTION(...)
27
28// Expands to a token of Prefix##<count>, where <count> is the number of variadic arguments.
29//
30// Example:
31// UE_APPEND_VA_ARG_COUNT(SOME_MACRO_) => SOME_MACRO_0
32// UE_APPEND_VA_ARG_COUNT(SOME_MACRO_, a, b, c) => SOME_MACRO_3
33#if !defined(_MSVC_TRADITIONAL) || !_MSVC_TRADITIONAL
34 #define UE_APPEND_VA_ARG_COUNT(Prefix, ...) UE_PRIVATE_APPEND_VA_ARG_COUNT(Prefix, ##__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
35#else
36 #define UE_APPEND_VA_ARG_COUNT(Prefix, ...) UE_PRIVATE_APPEND_VA_ARG_COUNT_INVOKE(UE_PRIVATE_APPEND_VA_ARG_COUNT, (Prefix, ##__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
37
38 // MSVC's traditional preprocessor doesn't handle the zero-argument case correctly, so we use a workaround.
39 // The workaround uses token pasting of Macro##ArgsInParens, which the conformant preprocessor doesn't like and emits C5103.
40 #define UE_PRIVATE_APPEND_VA_ARG_COUNT_INVOKE(Macro, ArgsInParens) UE_PRIVATE_APPEND_VA_ARG_COUNT_EXPAND(Macro##ArgsInParens)
41 #define UE_PRIVATE_APPEND_VA_ARG_COUNT_EXPAND(Arg) Arg
42#endif
43#define UE_PRIVATE_APPEND_VA_ARG_COUNT(Prefix,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,Count,...) Prefix##Count
44
45#define PREPROCESSOR_VA_ARG_COUNT(...) UE_VA_ARG_COUNT(__VA_ARGS__)
46#define PREPROCESSOR_APPEND_VA_ARG_COUNT(Prefix, ...) UE_APPEND_VA_ARG_COUNT(Prefix, ##__VA_ARGS__)
47#define PREPROCESSOR_NOTHING_FUNCTION(...) UE_EMPTY_FUNCTION(__VA_ARGS__)
48
49#endif
50
51#define PREPROCESSOR_TO_TEXT(x) TEXT(PREPROCESSOR_TO_STRING(x))
52
53/**
54 * @brief
55 * Implement preprocessor function overloading based on argument count for a set of macros following a distinct
56 * convention. Individual overloads must have a trailing number corresponding to the number of arguments they accept
57 *
58 * For example:
59 * @code
60 * #define FOO_3(a, b, c) a##b##c
61 * #define FOO_2(a, b) a##b
62 * #define FOO_1(a) a
63 *
64 * #define FOO(...) MACRO_OVERLOAD(FOO_, __VA_ARGS__)
65 *
66 * FOO(1) // -> 1
67 * FOO(1, 2) // -> 12
68 * FOO(1, 2, 3) // -> 123
69 * @endcode
70 */
71#define MACRO_OVERLOAD(prefix, ...) PREPROCESSOR_APPEND_VA_ARG_COUNT(prefix, __VA_ARGS__)(__VA_ARGS__)
72
73/** @brief Returns given default value when input value is empty */
74#define DEFAULT_ON_EMPTY(value, default) BOOST_PP_IF(BOOST_PP_CHECK_EMPTY(value), default, value)
75
76#define MCRO_VERSION_NUM_2(major, minor) \
77 ( ((0x000000000000FFFFULL & major) << 48) \
78 | ((0x000000000000FFFFULL & minor) << 32) \
79 )
80
81#define MCRO_VERSION_NUM_3(major, minor, patch) \
82 ( ((0x000000000000FFFFULL & major) << 48) \
83 | ((0x000000000000FFFFULL & minor) << 32) \
84 | ((0x000000000000FFFFULL & patch) << 16) \
85 )
86
87#define MCRO_VERSION_NUM_4(major, minor, patch, rev) \
88 ( ((0x000000000000FFFFULL & major) << 48) \
89 | ((0x000000000000FFFFULL & minor) << 32) \
90 | ((0x000000000000FFFFULL & patch) << 16) \
91 | ((0x000000000000FFFFULL & rev) << 0) \
92 )
93
94/**
95 * @brief Store a semantic version in an uint64 number.
96 * @param major `0xFFFF'0000'0000'0000`ULL
97 * @param minor `0x0000'FFFF'0000'0000`ULL
98 * @param patch `0x0000'0000'FFFF'0000`ULL
99 * @param rev `0x0000'0000'0000'FFFF`ULL
100 * @remarks Each component can go up to 65535
101 */
102#define VERSION_NUM(...) MACRO_OVERLOAD(MCRO_VERSION_NUM_, __VA_ARGS__)
103
104/** @brief VERSION_NUM representation of current Engine version */
105#define UNREAL_VERSION_NUM VERSION_NUM(ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, ENGINE_PATCH_VERSION)
106
107/** @brief Macro for conveniently comparing unreal version for code compile compatibility cases. */
108#define UNREAL_VERSION(op, ...) (UNREAL_VERSION_NUM op VERSION_NUM(__VA_ARGS__))
109
110// Forward function of Unreal before UE 5.5 is not constexpr
111#if UNREAL_VERSION(<, 5, 5)
112
113template <typename T>
114FORCEINLINE constexpr T&& ForwardConstExpr(typename TRemoveReference<T>::Type& Obj)
115{
116 return (T&&)Obj;
117}
118
119template <typename T>
120FORCEINLINE constexpr T&& ForwardConstExpr(typename TRemoveReference<T>::Type&& Obj)
121{
122 return (T&&)Obj;
123}
124
125#define MCRO_FORWARD_FUNCTION ForwardConstExpr
126
127#else
128
129#define MCRO_FORWARD_FUNCTION Forward
130
131#endif
132
133/** @brief Shorten forwarding expression with this macro so one may not need to specify explicit type */
134#define FWD(...) MCRO_FORWARD_FUNCTION<decltype(__VA_ARGS__)>(__VA_ARGS__)