rippled
Loading...
Searching...
No Matches
safe_cast.h
1#pragma once
2
3#include <xrpl/beast/utility/instrumentation.h>
4
5#include <type_traits>
6
7namespace xrpl {
8
9// safe_cast adds compile-time checks to a static_cast to ensure that
10// the destination can hold all values of the source. This is particularly
11// handy when the source or destination is an enumeration type.
12
13template <class Src, class Dest>
16 (std::is_signed<Src>::value != std::is_signed<Dest>::value ? sizeof(Dest) > sizeof(Src)
17 : sizeof(Dest) >= sizeof(Src));
18
19template <class Dest, class Src>
21safe_cast(Src s) noexcept
22{
23 static_assert(
24 std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
25 constexpr unsigned not_same = std::is_signed_v<Dest> != std::is_signed_v<Src>;
26 static_assert(
27 sizeof(Dest) >= sizeof(Src) + not_same,
28 "Destination is too small to hold all values of source");
29 return static_cast<Dest>(s);
30}
31
32template <class Dest, class Src>
34safe_cast(Src s) noexcept
35{
36 return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
37}
38
39template <class Dest, class Src>
41safe_cast(Src s) noexcept
42{
43 return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
44}
45
46// unsafe_cast explicitly flags a static_cast as not necessarily able to hold
47// all values of the source. It includes a compile-time check so that if
48// underlying types become safe, it can be converted to a safe_cast.
49
50template <class Dest, class Src>
52unsafe_cast(Src s) noexcept
53{
54 static_assert(
56 "Only unsafe if casting signed to unsigned or "
57 "destination is too small");
58 return static_cast<Dest>(s);
59}
60
61template <class Dest, class Src>
63unsafe_cast(Src s) noexcept
64{
65 return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
66}
67
68template <class Dest, class Src>
70unsafe_cast(Src s) noexcept
71{
72 return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
73}
74
75template <class Dest, class Src>
77inline Dest
78safe_downcast(Src* s) noexcept
79{
80#ifdef NDEBUG
81 return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
82#else
83 auto* result = dynamic_cast<Dest>(s);
84 XRPL_ASSERT(result != nullptr, "xrpl::safe_downcast : pointer downcast is valid");
85 return result;
86#endif
87}
88
89template <class Dest, class Src>
91inline Dest
92safe_downcast(Src& s) noexcept
93{
94#ifndef NDEBUG
95 XRPL_ASSERT(
96 dynamic_cast<std::add_pointer_t<std::remove_reference_t<Dest>>>(&s) != nullptr,
97 "xrpl::safe_downcast : reference downcast is valid");
98#endif
99 return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
100}
101
102} // namespace xrpl
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Dest safe_downcast(Src *s) noexcept
Definition safe_cast.h:78
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > unsafe_cast(Src s) noexcept
Definition safe_cast.h:52
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
Definition safe_cast.h:21