rippled
Loading...
Searching...
No Matches
safe_cast.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2018 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_BASICS_SAFE_CAST_H_INCLUDED
21#define RIPPLE_BASICS_SAFE_CAST_H_INCLUDED
22
23#include <type_traits>
24
25namespace ripple {
26
27// safe_cast adds compile-time checks to a static_cast to ensure that
28// the destination can hold all values of the source. This is particularly
29// handy when the source or destination is an enumeration type.
30
31template <class Dest, class Src>
32static constexpr bool is_safetocasttovalue_v =
36 ? sizeof(Dest) > sizeof(Src)
37 : sizeof(Dest) >= sizeof(Src));
38
39template <class Dest, class Src>
40inline constexpr std::
42 safe_cast(Src s) noexcept
43{
44 static_assert(
46 "Cannot cast signed to unsigned");
47 constexpr unsigned not_same =
49 static_assert(
50 sizeof(Dest) >= sizeof(Src) + not_same,
51 "Destination is too small to hold all values of source");
52 return static_cast<Dest>(s);
53}
54
55template <class Dest, class Src>
56inline constexpr std::
58 safe_cast(Src s) noexcept
59{
60 return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
61}
62
63template <class Dest, class Src>
64inline constexpr std::
66 safe_cast(Src s) noexcept
67{
68 return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
69}
70
71// unsafe_cast explicitly flags a static_cast as not necessarily able to hold
72// all values of the source. It includes a compile-time check so that if
73// underlying types become safe, it can be converted to a safe_cast.
74
75template <class Dest, class Src>
76inline constexpr std::
78 unsafe_cast(Src s) noexcept
79{
80 static_assert(
81 !is_safetocasttovalue_v<Dest, Src>,
82 "Only unsafe if casting signed to unsigned or "
83 "destination is too small");
84 return static_cast<Dest>(s);
85}
86
87template <class Dest, class Src>
88inline constexpr std::
90 unsafe_cast(Src s) noexcept
91{
92 return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
93}
94
95template <class Dest, class Src>
96inline constexpr std::
98 unsafe_cast(Src s) noexcept
99{
100 return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
101}
102
103} // namespace ripple
104
105#endif
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
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:42
static constexpr bool is_safetocasttovalue_v
Definition safe_cast.h:32
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:78