rippled
Loading...
Searching...
No Matches
include
xrpl
basics
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>
) &&
34
(
std::is_signed<Src>::value
||
std::is_unsigned<Dest>::value
) &&
35
(
std::is_signed<Src>::value
!=
std::is_signed<Dest>::value
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_same_v
T is_same_v
std::is_signed
std::is_unsigned
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:25
ripple::safe_cast
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
ripple::is_safetocasttovalue_v
static constexpr bool is_safetocasttovalue_v
Definition
safe_cast.h:32
ripple::unsafe_cast
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
type_traits
std::underlying_type_t
Generated by
1.9.8