rippled
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 
25 namespace 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 
31 template <class Dest, class Src>
32 static constexpr bool is_safetocasttovalue_v =
33  (std::is_integral_v<Src> && std::is_integral_v<Dest>)&&(
36  ? sizeof(Dest) > sizeof(Src)
37  : sizeof(Dest) >= sizeof(Src));
38 
39 template <class Dest, class Src>
40 inline constexpr std::
41  enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
42  safe_cast(Src s) noexcept
43 {
44  static_assert(
45  std::is_signed_v<Dest> || std::is_unsigned_v<Src>,
46  "Cannot cast signed to unsigned");
47  constexpr unsigned not_same =
48  std::is_signed_v<Dest> != std::is_signed_v<Src>;
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 
55 template <class Dest, class Src>
56 inline constexpr std::
57  enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
58  safe_cast(Src s) noexcept
59 {
60  return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
61 }
62 
63 template <class Dest, class Src>
64 inline constexpr std::
65  enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
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 
75 template <class Dest, class Src>
76 inline constexpr std::
77  enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
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 
87 template <class Dest, class Src>
88 inline constexpr std::
89  enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
90  unsafe_cast(Src s) noexcept
91 {
92  return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
93 }
94 
95 template <class Dest, class Src>
96 inline constexpr std::
97  enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
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
std::is_signed
std::is_unsigned
ripple::unsafe_cast
constexpr std::enable_if_t< std::is_same_v< typename Dest::unit_type, typename Src::unit_type > &&std::is_integral_v< typename Dest::value_type > &&std::is_integral_v< typename Src::value_type >, Dest > unsafe_cast(Src s) noexcept
Definition: FeeUnits.h:544
std::underlying_type_t
ripple::safe_cast
constexpr std::enable_if_t< std::is_same_v< typename Dest::unit_type, typename Src::unit_type > &&std::is_integral_v< typename Dest::value_type > &&std::is_integral_v< typename Src::value_type >, Dest > safe_cast(Src s) noexcept
Definition: FeeUnits.h:532
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::is_safetocasttovalue_v
static constexpr bool is_safetocasttovalue_v
Definition: safe_cast.h:32
type_traits