UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ResolveTypeAmbiguity.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
10#include "Templates/Requires.h"
11
38// Mixing any signed integral types with any other signed integral type results in same type as "X * Y", which is promoted to the type of the result of mixed arithmetic between the types
39#define MIX_SIGNED_INTS_2_ARGS_ACTUAL(Func, OptionalMarkup) \
40 template < \
41 typename Arg1, \
42 typename Arg2 \
43 UE_REQUIRES( \
44 !std::is_same_v<Arg1, Arg2> && \
45 std::is_signed_v<Arg1> && std::is_integral_v<Arg1> && \
46 std::is_signed_v<Arg2> && std::is_integral_v<Arg2> \
47 ) \
48 > \
49 static OptionalMarkup inline auto Func(Arg1 X, Arg2 Y) -> decltype(X * Y) \
50 { \
51 using ArgType = decltype(X * Y); \
52 return Func((ArgType)X, (ArgType)Y); \
53 }
54
55#define MIX_SIGNED_INTS_2_ARGS(Func) MIX_SIGNED_INTS_2_ARGS_ACTUAL(Func,)
56#define MIX_SIGNED_INTS_2_ARGS_CONSTEXPR(Func) MIX_SIGNED_INTS_2_ARGS_ACTUAL(Func, constexpr)
57
58// Mixing any signed integral types with any other signed integral type results in same type as "X * Y", which is promoted to the type of the result of mixed arithmetic between the types
59#define MIX_SIGNED_TYPES_3_ARGS_ACTUAL(Func, OptionalMarkup) \
60 template < \
61 typename Arg1, \
62 typename Arg2, \
63 typename Arg3 \
64 UE_REQUIRES( \
65 ( \
66 !std::is_same_v<Arg1, Arg2>> || \
67 !std::is_same_v<Arg2, Arg3>> || \
68 !std::is_same_v<Arg1, Arg3>> \
69 ) && \
70 std::is_signed_v<Arg1> && std::is_integral_v<Arg1> && \
71 std::is_signed_v<Arg2> && std::is_integral_v<Arg2> && \
72 std::is_signed_v<Arg3> && std::is_integral_v<Arg3> \
73 ) \
74 > \
75 static OptionalMarkup inline auto Func(Arg1 X, Arg2 Y, Arg3 Z) -> decltype(X * Y * Z) \
76 { \
77 using ArgType = decltype(X * Y * Z); \
78 return Func((ArgType)X, (ArgType)Y, (ArgType)Z); \
79 }
80
81#define MIX_SIGNED_INTS_3_ARGS(Func) MIX_SIGNED_INTS_3_ARGS_ACTUAL(Func,)
82#define MIX_SIGNED_INTS_3_ARGS_CONSTEXPR(Func) MIX_SIGNED_INTS_3_ARGS_ACTUAL(Func, constexpr)
83
84
85// Mixing float and double types with any other type results in same type as "X * Y", which is promoted to the floating point type with the highest precision of the argument types.
86#define MIX_FLOATS_2_ARGS(Func) \
87 template < \
88 typename Arg1, \
89 typename Arg2 \
90 UE_REQUIRES((std::is_floating_point_v<Arg1> || std::is_floating_point_v<Arg2>) && !std::is_same_v<Arg1, Arg2>) \
91 > \
92 static inline auto Func(Arg1 X, Arg2 Y) -> decltype(X * Y) \
93 { \
94 using ArgType = decltype(X * Y); \
95 return Func((ArgType)X, (ArgType)Y); \
96 }
97
98// Mixing float and double types with any other type results in same type as "X * Y", which is promoted to the floating point type with the highest precision of the argument types.
99#define MIX_FLOATS_3_ARGS(Func) \
100 template < \
101 typename Arg1, \
102 typename Arg2, \
103 typename Arg3 \
104 UE_REQUIRES( \
105 (std::is_floating_point_v<Arg1> || std::is_floating_point_v<Arg2> || std::is_floating_point_v<Arg3>) && \
106 (!std::is_same_v<Arg1, Arg2> || !std::is_same_v<Arg2, Arg3> || !std::is_same_v<Arg1, Arg3>) \
107 ) \
108 > \
109 static inline auto Func(Arg1 X, Arg2 Y, Arg3 Z) -> decltype(X * Y * Z) \
110 { \
111 using ArgType = decltype(X * Y * Z); \
112 return Func((ArgType)X, (ArgType)Y, (ArgType)Z); \
113 }
114
115// Resolve ambiguity between multiple arguments to functions returning a floating point type.
116// If no arguments are floating point, emits a warning and resolves to float by default.
117// Otherwise promotes to the highest precision floating point type of the arugments.
118
119#define RESOLVE_FLOAT_AMBIGUITY_2_ARGS(Func) \
120 MIX_FLOATS_2_ARGS(Func);
121
122#define RESOLVE_FLOAT_AMBIGUITY_3_ARGS(Func) \
123 MIX_FLOATS_3_ARGS(Func);
124
125
127
128// Mixing float and double types with any other type results in same type as "X * Y", which is promoted to the floating point type with the highest precision of the argument types.
129#define MIX_FLOATS_TO_TYPE_2_ARGS(Func, ReturnType) \
130 template < \
131 typename Arg1, \
132 typename Arg2 \
133 UE_REQUIRES( \
134 (std::is_floating_point_v<Arg1> || std::is_floating_point_v<Arg2>) && \
135 !std::is_same_v<Arg1, Arg2> \
136 ) \
137 > \
138 static inline ReturnType Func(Arg1 X, Arg2 Y) \
139 { \
140 using ArgType = decltype(X * Y); \
141 return Func((ArgType)X, (ArgType)Y); \
142 }
143
144// Mixing float and double types with any other type results in same type as "X * Y", which is promoted to the floating point type with the highest precision of the argument types.
145#define MIX_FLOATS_TO_TYPE_3_ARGS(Func, ReturnType) \
146 template < \
147 typename Arg1, \
148 typename Arg2, \
149 typename Arg3 \
150 UE_REQUIRES( \
151 (std::is_floating_point_v<Arg1> || std::is_floating_point_v<Arg2> || std::is_floating_point_v<Arg3>) && \
152 (!std::is_same_v<Arg1, Arg2> || !std::is_same_v<Arg1, Arg3> || !std::is_same_v<Arg2, Arg3>) \
153 ) \
154 > \
155 static inline ReturnType Func(Arg1 X, Arg2 Y, Arg3 Z) \
156 { \
157 using ArgType = decltype(X * Y * Z); \
158 return Func((ArgType)X, (ArgType)Y, (ArgType)Z); \
159 }
160
161// Resolve ambiguity between multiple arguments to functions returning a generic point type.
162// If no arguments are floating point, emits a warning and resolves to float by default.
163// Otherwise promotes to the highest precision floating point type of the arugments.
164
165#define RESOLVE_FLOAT_TO_TYPE_AMBIGUITY_2_ARGS(Func, ReturnType) \
166 MIX_FLOATS_TO_TYPE_2_ARGS(Func, ReturnType);
167
168#define RESOLVE_FLOAT_TO_TYPE_AMBIGUITY_3_ARGS(Func, ReturnType) \
169 MIX_FLOATS_TO_TYPE_3_ARGS(Func, ReturnType);
170
171// nicer names for the bool version
172#define RESOLVE_FLOAT_PREDICATE_AMBIGUITY_2_ARGS(Func) RESOLVE_FLOAT_TO_TYPE_AMBIGUITY_2_ARGS(Func, bool)
173#define RESOLVE_FLOAT_PREDICATE_AMBIGUITY_3_ARGS(Func) RESOLVE_FLOAT_TO_TYPE_AMBIGUITY_3_ARGS(Func, bool)