]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/safe_numerics/safe_integer_literal.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / safe_numerics / safe_integer_literal.hpp
CommitLineData
92f5a8d4
TL
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
19namespace boost {
20namespace safe_numerics {
21
22template<typename T, T N, class P, class E>
23class safe_literal_impl;
24
25template<typename T, T N, class P, class E>
26struct is_safe<safe_literal_impl<T, N, P, E> > : public std::true_type
27{};
28
29template<typename T, T N, class P, class E>
30struct get_promotion_policy<safe_literal_impl<T, N, P, E> > {
31 using type = P;
32};
33
34template<typename T, T N, class P, class E>
35struct get_exception_policy<safe_literal_impl<T, N, P, E> > {
36 using type = E;
37};
38template<typename T, T N, class P, class E>
39struct base_type<safe_literal_impl<T, N, P, E> > {
40 using type = T;
41};
42
43template<typename T, T N, class P, class E>
44constexpr T base_value(
45 const safe_literal_impl<T, N, P, E> &
46) {
47 return N;
48}
49
50template<typename CharT, typename Traits, typename T, T N, class P, class E>
51inline 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
65template<typename T, T N, class P, class E>
66class 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
87public:
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 {
f67539c2
TL
107 // if static values don't overlap, the program can never function
108 #if 1
109 constexpr const interval<R> r_interval;
110 static_assert(
111 ! r_interval.excludes(N),
112 "safe type cannot be constructed with this type"
113 );
114 #endif
115
116 return validate_detail<
117 R,
118 std::numeric_limits<R>::min(),
119 std::numeric_limits<R>::max(),
120 E
121 >::return_value(*this);
92f5a8d4
TL
122 }
123
124 // non mutating unary operators
125 constexpr safe_literal_impl<T, N, P, E> operator+() const { // unary plus
126 return safe_literal_impl<T, N, P, E>();
127 }
128 // after much consideration, I've permitted the resulting value of a unary
129 // - to change the type in accordance with the promotion policy.
130 // The C++ standard does invoke integral promotions so it's changing the type as well.
131
132 /* section 5.3.1 &8 of the C++ standard
133 The operand of the unary - operator shall have arithmetic or unscoped
134 enumeration type and the result is the negation of its operand. Integral
135 promotion is performed on integral or enumeration operands. The negative
136 of an unsigned quantity is computed by subtracting its value from 2n,
137 where n is the number of bits in the promoted operand. The type of the
138 result is the type of the promoted operand.
139 */
140 template<
141 typename Tx, Tx Nx, typename = std::enable_if_t<! checked::minus(Nx).exception()>
142 >
143 constexpr auto minus_helper() const {
144 return safe_literal_impl<Tx, -N, P, E>();
145 }
146
147 constexpr auto operator-() const { // unary minus
148 return minus_helper<T, N>();
149 }
150
151 /* section 5.3.1 &10 of the C++ standard
152 The operand of ~ shall have integral or unscoped enumeration type;
153 the result is the ones’ complement of its operand. Integral promotions
154 are performed. The type of the result is the type of the promoted operand.
155 constexpr safe_literal_impl<T, checked::bitwise_not(N), P, E> operator~() const { // invert bits
156 return safe_literal_impl<T, checked::bitwise_not(N), P, E>();
157 }
158 */
159 template<
160 typename Tx, Tx Nx, typename = std::enable_if_t<! checked::bitwise_not(Nx).exception()>
161 >
162 constexpr auto not_helper() const {
163 return safe_literal_impl<Tx, ~N, P, E>();
164 }
165
166 constexpr auto operator~() const { // unary minus
167 return not_helper<T, N>();
168 }
169};
170
171template<
172 std::intmax_t N,
173 class P = void,
174 class E = void
175>
176using safe_signed_literal = safe_literal_impl<
177 typename utility::signed_stored_type<N, N>,
178 N,
179 P,
180 E
181>;
182
183template<
184 std::uintmax_t N,
185 class P = void,
186 class E = void
187>
188using safe_unsigned_literal = safe_literal_impl<
189 typename utility::unsigned_stored_type<N, N>,
190 N,
191 P,
192 E
193>;
194
195template<
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>
205constexpr auto make_safe_literal_impl() {
206 return boost::safe_numerics::safe_signed_literal<N, P, E>();
207}
208
209template<
210 class T,
211 T N,
212 class P = void,
213 class E = void,
214 typename std::enable_if<
215 ! std::is_signed<T>::value,
216 int
217 >::type = 0
218>
219constexpr auto make_safe_literal_impl() {
220 return boost::safe_numerics::safe_unsigned_literal<N, P, E>();
221}
222
223} // safe_numerics
224} // boost
225
226#define make_safe_literal(n, P, E) \
227 boost::safe_numerics::make_safe_literal_impl<decltype(n), n, P, E>()
228
229/////////////////////////////////////////////////////////////////
230// numeric limits for safe_literal etc.
231
232#include <limits>
233
234namespace std {
235
236template<
237 typename T,
238 T N,
239 class P,
240 class E
241>
242class numeric_limits<boost::safe_numerics::safe_literal_impl<T, N, P, E> >
243 : public std::numeric_limits<T>
244{
245 using SL = boost::safe_numerics::safe_literal_impl<T, N, P, E>;
246public:
247 constexpr static SL lowest() noexcept {
248 return SL();
249 }
250 constexpr static SL min() noexcept {
251 return SL();
252 }
253 constexpr static SL max() noexcept {
254 return SL();
255 }
256};
257
258} // std
259
260#endif // BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP