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 Src, class Dest>
35 ? sizeof(Dest) > sizeof(Src)
36 : sizeof(Dest) >= sizeof(Src));
37
38template <class Dest, class Src>
39inline constexpr std::
41 safe_cast(Src s) noexcept
42{
43 static_assert(
45 "Cannot cast signed to unsigned");
46 constexpr unsigned not_same =
48 static_assert(
49 sizeof(Dest) >= sizeof(Src) + not_same,
50 "Destination is too small to hold all values of source");
51 return static_cast<Dest>(s);
52}
53
54template <class Dest, class Src>
55inline constexpr std::
57 safe_cast(Src s) noexcept
58{
59 return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
60}
61
62template <class Dest, class Src>
63inline constexpr std::
65 safe_cast(Src s) noexcept
66{
67 return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
68}
69
70// unsafe_cast explicitly flags a static_cast as not necessarily able to hold
71// all values of the source. It includes a compile-time check so that if
72// underlying types become safe, it can be converted to a safe_cast.
73
74template <class Dest, class Src>
75inline constexpr std::
77 unsafe_cast(Src s) noexcept
78{
79 static_assert(
81 "Only unsafe if casting signed to unsigned or "
82 "destination is too small");
83 return static_cast<Dest>(s);
84}
85
86template <class Dest, class Src>
87inline constexpr std::
89 unsafe_cast(Src s) noexcept
90{
91 return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
92}
93
94template <class Dest, class Src>
95inline constexpr std::
97 unsafe_cast(Src s) noexcept
98{
99 return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
100}
101
102} // namespace ripple
103
104#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:41
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:77