17hi_warning_ignore_msvc(26472);
22hi_warning_ignore_msvc(26467);
25hi_warning_ignore_msvc(26496);
27namespace hi::inline
v1 {
29[[nodiscard]]
constexpr T
copy(T value)
noexcept
36template<
typename Out, std::derived_from<std::remove_po
inter_t<Out>> In>
37[[nodiscard]]
constexpr Out
up_cast(In *rhs)
noexcept
38 requires std::is_pointer_v<Out> and (std::is_const_v<std::remove_pointer_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_pointer_t<Out>>)
40 return static_cast<Out
>(rhs);
46[[nodiscard]]
constexpr Out
up_cast(nullptr_t)
noexcept
47 requires std::is_pointer_v<Out>
54template<
typename Out, std::derived_from<std::remove_reference_t<Out>> In>
55[[nodiscard]]
constexpr Out
up_cast(In& rhs)
noexcept
56 requires std::is_reference_v<Out> and (std::is_const_v<std::remove_reference_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_reference_t<Out>>)
58 return static_cast<Out
>(rhs);
68template<
typename Out, base_of<std::remove_po
inter_t<Out>> In>
69[[nodiscard]]
constexpr Out
down_cast(In *rhs)
noexcept
70 requires std::is_pointer_v<Out> and (std::is_const_v<std::remove_pointer_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_pointer_t<Out>>)
72 hi_axiom(rhs ==
nullptr or
dynamic_cast<Out
>(rhs) !=
nullptr);
73 return static_cast<Out
>(rhs);
81[[nodiscard]]
constexpr Out
down_cast(nullptr_t)
noexcept
82 requires std::is_pointer_v<Out>
93template<
typename Out, base_of<std::remove_reference_t<Out>> In>
94[[nodiscard]]
constexpr Out
down_cast(In& rhs)
noexcept
95 requires std::is_reference_v<Out> and (
96 std::is_const_v<std::remove_reference_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_reference_t<Out>>)
98 hi_axiom(
dynamic_cast<std::add_pointer_t<std::remove_reference_t<Out>
>>(
std::addressof(rhs)) !=
nullptr);
99 return static_cast<Out
>(rhs);
104template<arithmetic Out, arithmetic In>
105[[nodiscard]]
constexpr Out
wide_cast(In rhs)
noexcept requires(type_in_range_v<Out, In>)
107 return static_cast<Out
>(rhs);
112template<arithmetic Out>
115 return static_cast<Out
>(rhs);
120template<arithmetic Out, arithmetic In>
121[[nodiscard]]
constexpr bool narrow_validate(Out out, In in)
noexcept
124 auto r = (in ==
static_cast<In
>(out));
129 r &= (in < In{}) == (out < Out{});
145template<arithmetic Out, arithmetic In>
146[[nodiscard]]
constexpr Out
narrow(In rhs)
noexcept(type_in_range_v<Out, In>)
148 if constexpr (type_in_range_v<Out, In>) {
149 return static_cast<Out
>(rhs);
151 hilet r =
static_cast<Out
>(rhs);
153 if (not detail::narrow_validate(r, rhs)) {
163template<std::
unsigned_
integral Out, std::
unsigned_
integral In>
168 r =
static_cast<Out
>(rhs);
181template<arithmetic Out, arithmetic In>
184 if constexpr (type_in_range_v<Out, In>) {
185 return static_cast<Out
>(rhs);
187 hilet r =
static_cast<Out
>(rhs);
188 hi_axiom(detail::narrow_validate(r, rhs));
193template<std::
integral Out, arithmetic In>
194[[nodiscard]]
constexpr Out truncate(In rhs)
noexcept
196 return static_cast<Out
>(rhs);
209template<std::
integral Out, std::
integral In>
212 using in_unsigned_type = std::make_unsigned_t<In>;
213 using out_unsigned_type = std::make_unsigned_t<Out>;
216 auto in_unsigned =
static_cast<in_unsigned_type
>(rhs);
217 auto out_unsigned = narrow_cast<out_unsigned_type>(in_unsigned);
218 return static_cast<Out
>(out_unsigned);
221template<std::
integral Out>
222[[nodiscard]]
constexpr Out char_cast(std::byte rhs)
noexcept
224 return char_cast<Out>(
static_cast<uint8_t
>(rhs));
229template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
232 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of low_bit_cast must be half the size of the input");
233 return static_cast<OutType
>(value);
238template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
241 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of high_bit_cast must be half the size of the input");
242 return static_cast<OutType
>(value >>
sizeof(OutType) * CHAR_BIT);
247template<std::
signed_
integral OutType, std::
signed_
integral InType>
248[[nodiscard]]
constexpr OutType low_bit_cast(InType value)
noexcept
250 using UInType = std::make_unsigned_t<InType>;
251 using UOutType = std::make_unsigned_t<OutType>;
252 return static_cast<OutType
>(low_bit_cast<UOutType>(
static_cast<UInType
>(value)));
257template<std::
signed_
integral OutType, std::
signed_
integral InType>
258[[nodiscard]]
constexpr OutType
high_bit_cast(InType value)
noexcept
260 using UInType = std::make_unsigned_t<InType>;
261 using UOutType = std::make_unsigned_t<OutType>;
262 return static_cast<OutType
>(high_bit_cast<UOutType>(
static_cast<UInType
>(value)));
267template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
268[[nodiscard]]
constexpr OutType
low_bit_cast(InType value)
noexcept
270 using UInType = std::make_unsigned_t<InType>;
271 return low_bit_cast<OutType>(
static_cast<UInType
>(value));
276template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
277[[nodiscard]]
constexpr OutType
high_bit_cast(InType value)
noexcept
279 using UInType = std::make_unsigned_t<InType>;
280 return high_bit_cast<OutType>(
static_cast<UInType
>(value));
285template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
288 static_assert(
sizeof(OutType) ==
sizeof(InType) * 2,
"Return value of merge_bit_cast must be double the size of the input");
290 OutType r =
static_cast<OutType
>(
hi);
291 r <<=
sizeof(InType) * CHAR_BIT;
292 r |=
static_cast<OutType
>(lo);
298template<std::
signed_
integral OutType, std::
signed_
integral InType>
299[[nodiscard]]
constexpr OutType merge_bit_cast(InType
hi, InType lo)
noexcept
301 using UInType = std::make_unsigned_t<InType>;
302 using UOutType = std::make_unsigned_t<OutType>;
303 return static_cast<OutType
>(merge_bit_cast<UOutType>(
static_cast<UInType
>(
hi),
static_cast<UInType
>(lo)));
308template<std::
signed_
integral OutType, std::
unsigned_
integral InType>
309[[nodiscard]]
constexpr OutType
merge_bit_cast(InType
hi, InType lo)
noexcept
311 using UOutType = std::make_unsigned_t<OutType>;
312 return narrow_cast<OutType>(merge_bit_cast<UOutType>(
hi, lo));
315[[nodiscard]]
constexpr auto to_underlying(scoped_enum
auto rhs)
noexcept
317 return static_cast<std::underlying_type_t<decltype(rhs)
>>(rhs);
321[[nodiscard]]
constexpr bool to_bool(T&& rhs)
noexcept requires(
requires(T&& x) {
static_cast<bool>(std::forward<T>(x)); })
323 return static_cast<bool>(std::forward<T>(rhs));
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
constexpr OutType merge_bit_cast(InType hi, InType lo) noexcept
Return the upper half of the input value.
Definition cast.hpp:286
constexpr Out wide_cast(In rhs) noexcept
Cast a number to a type that will be able to represent all values without loss of precision.
Definition cast.hpp:105
constexpr OutType high_bit_cast(InType value) noexcept
Return the upper half of the input value.
Definition cast.hpp:239
constexpr Out saturate_cast(In rhs) noexcept
Cast an unsigned number and saturate on overflow.
Definition cast.hpp:164
constexpr Out up_cast(In *rhs) noexcept
Cast a pointer to a class to its base class or itself.
Definition cast.hpp:37
constexpr Out narrow(In rhs) noexcept(type_in_range_v< Out, In >)
Cast numeric values without loss of precision.
Definition cast.hpp:146
constexpr Out char_cast(In rhs) noexcept
Cast a character.
Definition cast.hpp:210
constexpr OutType low_bit_cast(InType value) noexcept
Return the low half of the input value.
Definition cast.hpp:230
constexpr Out down_cast(In *rhs) noexcept
Cast a pointer to a class to its derived class or itself.
Definition cast.hpp:69
constexpr Out narrow_cast(In rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:182
The HikoGUI namespace.
Definition ascii.hpp:19