]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/safe_numerics/safe_integer_literal.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / safe_numerics / safe_integer_literal.hpp
1 #ifndef BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
2 #define BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
3
4 // Copyright (c) 2012 Robert Ramey
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9
10 #include <cstdint> // for intmax_t/uintmax_t
11 #include <iosfwd>
12 #include <type_traits> // conditional, enable_if
13 #include <boost/mp11/utility.hpp>
14
15 #include "utility.hpp"
16 #include "safe_integer.hpp"
17 #include "checked_integer.hpp"
18
19 namespace boost {
20 namespace safe_numerics {
21
22 template<typename T, T N, class P, class E>
23 class safe_literal_impl;
24
25 template<typename T, T N, class P, class E>
26 struct is_safe<safe_literal_impl<T, N, P, E> > : public std::true_type
27 {};
28
29 template<typename T, T N, class P, class E>
30 struct get_promotion_policy<safe_literal_impl<T, N, P, E> > {
31 using type = P;
32 };
33
34 template<typename T, T N, class P, class E>
35 struct get_exception_policy<safe_literal_impl<T, N, P, E> > {
36 using type = E;
37 };
38 template<typename T, T N, class P, class E>
39 struct base_type<safe_literal_impl<T, N, P, E> > {
40 using type = T;
41 };
42
43 template<typename T, T N, class P, class E>
44 constexpr T base_value(
45 const safe_literal_impl<T, N, P, E> &
46 ) {
47 return N;
48 }
49
50 template<typename CharT, typename Traits, typename T, T N, class P, class E>
51 inline std::basic_ostream<CharT, Traits> & operator<<(
52 std::basic_ostream<CharT, Traits> & os,
53 const safe_literal_impl<T, N, P, E> &
54 ){
55 return os << (
56 (std::is_same<T, signed char>::value
57 || std::is_same<T, unsigned char>::value
58 ) ?
59 static_cast<int>(N)
60 :
61 N
62 );
63 }
64
65 template<typename T, T N, class P, class E>
66 class safe_literal_impl {
67
68 template<
69 class CharT,
70 class Traits
71 >
72 friend std::basic_ostream<CharT, Traits> & operator<<(
73 std::basic_ostream<CharT, Traits> & os,
74 const safe_literal_impl &
75 ){
76 return os << (
77 (::std::is_same<T, signed char>::value
78 || ::std::is_same<T, unsigned char>::value
79 || ::std::is_same<T, wchar_t>::value
80 ) ?
81 static_cast<int>(N)
82 :
83 N
84 );
85 };
86
87 public:
88
89 ////////////////////////////////////////////////////////////
90 // constructors
91 // default constructor
92 constexpr safe_literal_impl(){}
93
94 /////////////////////////////////////////////////////////////////
95 // casting operators for intrinsic integers
96 // convert to any type which is not safe. safe types need to be
97 // excluded to prevent ambiguous function selection which
98 // would otherwise occur
99 template<
100 class R,
101 typename std::enable_if<
102 ! boost::safe_numerics::is_safe<R>::value,
103 int
104 >::type = 0
105 >
106 constexpr operator R () const {
107 return N;
108 }
109
110 // non mutating unary operators
111 constexpr safe_literal_impl<T, N, P, E> operator+() const { // unary plus
112 return safe_literal_impl<T, N, P, E>();
113 }
114 // after much consideration, I've permitted the resulting value of a unary
115 // - to change the type in accordance with the promotion policy.
116 // The C++ standard does invoke integral promotions so it's changing the type as well.
117
118 /* section 5.3.1 &8 of the C++ standard
119 The operand of the unary - operator shall have arithmetic or unscoped
120 enumeration type and the result is the negation of its operand. Integral
121 promotion is performed on integral or enumeration operands. The negative
122 of an unsigned quantity is computed by subtracting its value from 2n,
123 where n is the number of bits in the promoted operand. The type of the
124 result is the type of the promoted operand.
125 */
126 template<
127 typename Tx, Tx Nx, typename = std::enable_if_t<! checked::minus(Nx).exception()>
128 >
129 constexpr auto minus_helper() const {
130 return safe_literal_impl<Tx, -N, P, E>();
131 }
132
133 constexpr auto operator-() const { // unary minus
134 return minus_helper<T, N>();
135 }
136
137 /* section 5.3.1 &10 of the C++ standard
138 The operand of ~ shall have integral or unscoped enumeration type;
139 the result is the ones’ complement of its operand. Integral promotions
140 are performed. The type of the result is the type of the promoted operand.
141 constexpr safe_literal_impl<T, checked::bitwise_not(N), P, E> operator~() const { // invert bits
142 return safe_literal_impl<T, checked::bitwise_not(N), P, E>();
143 }
144 */
145 template<
146 typename Tx, Tx Nx, typename = std::enable_if_t<! checked::bitwise_not(Nx).exception()>
147 >
148 constexpr auto not_helper() const {
149 return safe_literal_impl<Tx, ~N, P, E>();
150 }
151
152 constexpr auto operator~() const { // unary minus
153 return not_helper<T, N>();
154 }
155 };
156
157 template<
158 std::intmax_t N,
159 class P = void,
160 class E = void
161 >
162 using safe_signed_literal = safe_literal_impl<
163 typename utility::signed_stored_type<N, N>,
164 N,
165 P,
166 E
167 >;
168
169 template<
170 std::uintmax_t N,
171 class P = void,
172 class E = void
173 >
174 using safe_unsigned_literal = safe_literal_impl<
175 typename utility::unsigned_stored_type<N, N>,
176 N,
177 P,
178 E
179 >;
180
181 template<
182 class T,
183 T N,
184 class P = void,
185 class E = void,
186 typename std::enable_if<
187 std::is_signed<T>::value,
188 int
189 >::type = 0
190 >
191 constexpr auto make_safe_literal_impl() {
192 return boost::safe_numerics::safe_signed_literal<N, P, E>();
193 }
194
195 template<
196 class T,
197 T N,
198 class P = void,
199 class E = void,
200 typename std::enable_if<
201 ! std::is_signed<T>::value,
202 int
203 >::type = 0
204 >
205 constexpr auto make_safe_literal_impl() {
206 return boost::safe_numerics::safe_unsigned_literal<N, P, E>();
207 }
208
209 } // safe_numerics
210 } // boost
211
212 #define make_safe_literal(n, P, E) \
213 boost::safe_numerics::make_safe_literal_impl<decltype(n), n, P, E>()
214
215 /////////////////////////////////////////////////////////////////
216 // numeric limits for safe_literal etc.
217
218 #include <limits>
219
220 namespace std {
221
222 template<
223 typename T,
224 T N,
225 class P,
226 class E
227 >
228 class numeric_limits<boost::safe_numerics::safe_literal_impl<T, N, P, E> >
229 : public std::numeric_limits<T>
230 {
231 using SL = boost::safe_numerics::safe_literal_impl<T, N, P, E>;
232 public:
233 constexpr static SL lowest() noexcept {
234 return SL();
235 }
236 constexpr static SL min() noexcept {
237 return SL();
238 }
239 constexpr static SL max() noexcept {
240 return SL();
241 }
242 };
243
244 } // std
245
246 #endif // BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP