openMSX
narrow.hh
Go to the documentation of this file.
1#ifndef NARROW_HH
2#define NARROW_HH
3
4#include "inline.hh"
5#include <cassert>
6#include <type_traits>
7#include <utility>
8
9// Inspired by GSL narrow
10// https://github.com/microsoft/GSL/blob/main/include/gsl/narrow
11//
12// narrow_cast(): a searchable way to do narrowing casts of values
13// narrow(): a checked version of narrow_cast(), asserts that the
14// numerical value remains unchanged
15//
16// The main difference between this version and the GSL version is that we
17// assert (we don't want any overhead in non-assert build), while GSL throws an
18// exception.
19
20template<typename To, typename From>
21constexpr To narrow_cast(From&& from) noexcept
22{
23 return static_cast<To>(std::forward<From>(from));
24}
25
26ALWAYS_INLINE constexpr void narrow_assert(bool ok)
27{
28 if (!ok) {
29#ifdef UNITTEST
30 throw "narrow() error";
31#else
32 assert(false && "narrow() error");
33#endif
34 }
35}
36
37template<typename To, typename From> constexpr To narrow(From from)
38#ifndef UNITTEST
39 noexcept
40#endif
41{
42 static_assert(std::is_arithmetic_v<From>);
43 static_assert(std::is_arithmetic_v<To>);
44
45 const To to = narrow_cast<To>(from);
46
47 narrow_assert(static_cast<From>(to) == from);
48 if constexpr (std::is_signed_v<From> != std::is_signed_v<To>) {
49 narrow_assert((to < To{}) == (from < From{}));
50 }
51
52 return to;
53}
54
55#endif
#define ALWAYS_INLINE
Definition inline.hh:16
constexpr To narrow_cast(From &&from) noexcept
Definition narrow.hh:21
ALWAYS_INLINE constexpr void narrow_assert(bool ok)
Definition narrow.hh:26
constexpr To narrow(From from) noexcept
Definition narrow.hh:37