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)) {
169template<arithmetic Out, arithmetic In>
172 if constexpr (type_in_range_v<Out, In>) {
173 return static_cast<Out
>(rhs);
175 hilet r =
static_cast<Out
>(rhs);
176 hi_axiom(detail::narrow_validate(r, rhs));
181template<std::
integral Out, arithmetic In>
182[[nodiscard]]
constexpr Out truncate(In rhs)
noexcept
184 return static_cast<Out
>(rhs);
197template<std::
integral Out, std::
integral In>
200 using in_unsigned_type = std::make_unsigned_t<In>;
201 using out_unsigned_type = std::make_unsigned_t<Out>;
204 auto in_unsigned =
static_cast<in_unsigned_type
>(rhs);
205 auto out_unsigned = narrow_cast<out_unsigned_type>(in_unsigned);
206 return static_cast<Out
>(out_unsigned);
209template<std::
integral Out>
210[[nodiscard]]
constexpr Out char_cast(std::byte rhs)
noexcept
212 return char_cast<Out>(
static_cast<uint8_t
>(rhs));
217template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
220 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of low_bit_cast must be half the size of the input");
221 return static_cast<OutType
>(value);
226template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
229 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of high_bit_cast must be half the size of the input");
230 return static_cast<OutType
>(value >>
sizeof(OutType) * CHAR_BIT);
235template<std::
signed_
integral OutType, std::
signed_
integral InType>
236[[nodiscard]]
constexpr OutType low_bit_cast(InType value)
noexcept
238 using UInType = std::make_unsigned_t<InType>;
239 using UOutType = std::make_unsigned_t<OutType>;
240 return static_cast<OutType
>(low_bit_cast<UOutType>(
static_cast<UInType
>(value)));
245template<std::
signed_
integral OutType, std::
signed_
integral InType>
246[[nodiscard]]
constexpr OutType
high_bit_cast(InType value)
noexcept
248 using UInType = std::make_unsigned_t<InType>;
249 using UOutType = std::make_unsigned_t<OutType>;
250 return static_cast<OutType
>(high_bit_cast<UOutType>(
static_cast<UInType
>(value)));
255template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
256[[nodiscard]]
constexpr OutType
low_bit_cast(InType value)
noexcept
258 using UInType = std::make_unsigned_t<InType>;
259 return low_bit_cast<OutType>(
static_cast<UInType
>(value));
264template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
265[[nodiscard]]
constexpr OutType
high_bit_cast(InType value)
noexcept
267 using UInType = std::make_unsigned_t<InType>;
268 return high_bit_cast<OutType>(
static_cast<UInType
>(value));
273template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
276 static_assert(
sizeof(OutType) ==
sizeof(InType) * 2,
"Return value of merge_bit_cast must be double the size of the input");
278 OutType r =
static_cast<OutType
>(
hi);
279 r <<=
sizeof(InType) * CHAR_BIT;
280 r |=
static_cast<OutType
>(lo);
286template<std::
signed_
integral OutType, std::
signed_
integral InType>
287[[nodiscard]]
constexpr OutType merge_bit_cast(InType
hi, InType lo)
noexcept
289 using UInType = std::make_unsigned_t<InType>;
290 using UOutType = std::make_unsigned_t<OutType>;
291 return static_cast<OutType
>(merge_bit_cast<UOutType>(
static_cast<UInType
>(
hi),
static_cast<UInType
>(lo)));
296template<std::
signed_
integral OutType, std::
unsigned_
integral InType>
297[[nodiscard]]
constexpr OutType
merge_bit_cast(InType
hi, InType lo)
noexcept
299 using UOutType = std::make_unsigned_t<OutType>;
300 return narrow_cast<OutType>(merge_bit_cast<UOutType>(
hi, lo));
303[[nodiscard]]
constexpr auto to_underlying(scoped_enum
auto rhs)
noexcept
305 return static_cast<std::underlying_type_t<decltype(rhs)
>>(rhs);
309[[nodiscard]]
constexpr bool to_bool(T&& rhs)
noexcept requires(
requires(T&& x) {
static_cast<bool>(std::forward<T>(x)); })
311 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:274
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:227
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:198
constexpr OutType low_bit_cast(InType value) noexcept
Return the low half of the input value.
Definition cast.hpp:218
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:170
The HikoGUI namespace.
Definition ascii.hpp:19