]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/safe_numerics/safe_base.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / safe_numerics / safe_base.hpp
1 #ifndef BOOST_NUMERIC_SAFE_BASE_HPP
2 #define BOOST_NUMERIC_SAFE_BASE_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 <limits>
11 #include <type_traits> // is_integral, enable_if, conditional is_convertible
12 #include <boost/config.hpp> // BOOST_CLANG
13 #include "concept/exception_policy.hpp"
14 #include "concept/promotion_policy.hpp"
15
16 #include "safe_common.hpp"
17 #include "exception_policies.hpp"
18
19 #include "boost/concept/assert.hpp"
20
21 namespace boost {
22 namespace safe_numerics {
23
24 /////////////////////////////////////////////////////////////////
25 // forward declarations to support friend function declarations
26 // in safe_base
27
28 template<
29 class Stored,
30 Stored Min,
31 Stored Max,
32 class P, // promotion polic
33 class E // exception policy
34 >
35 class safe_base;
36
37 template<
38 class T,
39 T Min,
40 T Max,
41 class P,
42 class E
43 >
44 struct is_safe<safe_base<T, Min, Max, P, E> > : public std::true_type
45 {};
46
47 template<
48 class T,
49 T Min,
50 T Max,
51 class P,
52 class E
53 >
54 struct get_promotion_policy<safe_base<T, Min, Max, P, E> > {
55 using type = P;
56 };
57
58 template<
59 class T,
60 T Min,
61 T Max,
62 class P,
63 class E
64 >
65 struct get_exception_policy<safe_base<T, Min, Max, P, E> > {
66 using type = E;
67 };
68
69 template<
70 class T,
71 T Min,
72 T Max,
73 class P,
74 class E
75 >
76 struct base_type<safe_base<T, Min, Max, P, E> > {
77 using type = T;
78 };
79
80 template<
81 class T,
82 T Min,
83 T Max,
84 class P,
85 class E
86 >
87 constexpr T base_value(
88 const safe_base<T, Min, Max, P, E> & st
89 ) {
90 return static_cast<T>(st);
91 }
92
93 template<
94 typename T,
95 T N,
96 class P, // promotion policy
97 class E // exception policy
98 >
99 class safe_literal_impl;
100
101 // works for both GCC and clang
102 #if BOOST_CLANG==1
103 #pragma GCC diagnostic push
104 #pragma GCC diagnostic ignored "-Wmismatched-tags"
105 #endif
106
107 /////////////////////////////////////////////////////////////////
108 // Main implementation
109
110 template<
111 class Stored,
112 Stored Min,
113 Stored Max,
114 class P, // promotion polic
115 class E // exception policy
116 >
117 class safe_base {
118 private:
119 BOOST_CONCEPT_ASSERT((PromotionPolicy<P>));
120 BOOST_CONCEPT_ASSERT((ExceptionPolicy<E>));
121 Stored m_t;
122
123 template<
124 class StoredX,
125 StoredX MinX,
126 StoredX MaxX,
127 class PX, // promotion polic
128 class EX // exception policy
129 >
130 friend class safe_base;
131
132 friend class std::numeric_limits<safe_base>;
133
134 template<class T>
135 constexpr Stored validated_cast(const T & t) const;
136
137 // stream support
138
139 template<class CharT, class Traits>
140 void output(std::basic_ostream<CharT, Traits> & os) const;
141
142 // note usage of friend declaration to mark function as
143 // a global function rather than a member function. If
144 // this is not done, the compiler will confuse this with
145 // a member operator overload on the << operator. Weird
146 // I know. But it's documented here
147 // http://en.cppreference.com/w/cpp/language/friend
148 // under the heading "Template friend operators"
149 template<class CharT, class Traits>
150 friend std::basic_ostream<CharT, Traits> &
151 operator<<(
152 std::basic_ostream<CharT, Traits> & os,
153 const safe_base & t
154 ){
155 t.output(os);
156 return os;
157 }
158
159 template<class CharT, class Traits>
160 void input(std::basic_istream<CharT, Traits> & is);
161
162 // see above
163 template<class CharT, class Traits>
164 friend inline std::basic_istream<CharT, Traits> &
165 operator>>(
166 std::basic_istream<CharT, Traits> & is,
167 safe_base & t
168 ){
169 t.input(is);
170 return is;
171 }
172
173 public:
174 ////////////////////////////////////////////////////////////
175 // constructors
176
177 constexpr safe_base();
178
179 struct skip_validation{};
180
181 constexpr explicit safe_base(const Stored & rhs, skip_validation);
182
183 // construct an instance of a safe type from an instance of a convertible underlying type.
184 template<
185 class T,
186 typename std::enable_if<
187 std::is_convertible<T, Stored>::value,
188 bool
189 >::type = 0
190 >
191 constexpr /*explicit*/ safe_base(const T & t);
192
193 // construct an instance of a safe type from a literal value
194 template<typename T, T N, class Px, class Ex>
195 constexpr /*explicit*/ safe_base(const safe_literal_impl<T, N, Px, Ex> & t);
196
197 // note: Rule of Five. Supply all or none of the following
198 // a) user-defined destructor
199 ~safe_base() = default;
200 // b) copy-constructor
201 constexpr safe_base(const safe_base &) = default;
202 // c) copy-assignment
203 constexpr safe_base & operator=(const safe_base &) = default;
204 // d) move constructor
205 constexpr safe_base(safe_base &&) = default;
206 // e) move assignment operator
207 constexpr safe_base & operator=(safe_base &&) = default;
208
209 /////////////////////////////////////////////////////////////////
210 // casting operators for intrinsic integers
211 // convert to any type which is not safe. safe types need to be
212 // excluded to prevent ambiguous function selection which
213 // would otherwise occur. validity of safe types is checked in
214 // the constructor of safe types
215 template<
216 class R,
217 typename std::enable_if<
218 ! boost::safe_numerics::is_safe<R>::value,
219 int
220 >::type = 0
221 >
222 constexpr /*explicit*/ operator R () const;
223
224 /////////////////////////////////////////////////////////////////
225 // modification binary operators
226 template<class T>
227 constexpr safe_base &
228 operator=(const T & rhs){
229 m_t = validated_cast(rhs);
230 return *this;
231 }
232
233 // mutating unary operators
234 safe_base & operator++(){ // pre increment
235 return *this = *this + 1;
236 }
237 safe_base & operator--(){ // pre decrement
238 return *this = *this - 1;
239 }
240 safe_base operator++(int){ // post increment
241 safe_base old_t = *this;
242 ++(*this);
243 return old_t;
244 }
245 safe_base operator--(int){ // post decrement
246 safe_base old_t = *this;
247 --(*this);
248 return old_t;
249 }
250 // non mutating unary operators
251 constexpr auto operator+() const { // unary plus
252 return *this;
253 }
254 // after much consideration, I've permited the resulting value of a unary
255 // - to change the type. The C++ standard does invoke integral promotions
256 // so it's changing the type as well.
257
258 /* section 5.3.1 &8 of the C++ standard
259 The operand of the unary - operator shall have arithmetic or unscoped
260 enumeration type and the result is the negation of its operand. Integral
261 promotion is performed on integral or enumeration operands. The negative
262 of an unsigned quantity is computed by subtracting its value from 2n,
263 where n is the number of bits in the promoted operand. The type of the
264 result is the type of the promoted operand.
265 */
266 constexpr auto operator-() const { // unary minus
267 // if this is a unsigned type and the promotion policy is native
268 // the result will be unsigned. But then the operation will fail
269 // according to the requirements of arithmetic correctness.
270 // if this is an unsigned type and the promotion policy is automatic.
271 // the result will be signed.
272 return 0 - *this;
273 }
274 /* section 5.3.1 &10 of the C++ standard
275 The operand of ~ shall have integral or unscoped enumeration type;
276 the result is the ones’ complement of its operand. Integral promotions
277 are performed. The type of the result is the type of the promoted operand.
278 */
279 constexpr auto operator~() const { // complement
280 return ~Stored(0u) ^ *this;
281 }
282 };
283
284 } // safe_numerics
285 } // boost
286
287 /////////////////////////////////////////////////////////////////
288 // numeric limits for safe<int> etc.
289
290 #include <limits>
291
292 namespace std {
293
294 template<
295 class T,
296 T Min,
297 T Max,
298 class P,
299 class E
300 >
301 class numeric_limits<boost::safe_numerics::safe_base<T, Min, Max, P, E> >
302 : public std::numeric_limits<T>
303 {
304 using SB = boost::safe_numerics::safe_base<T, Min, Max, P, E>;
305 public:
306 constexpr static SB lowest() noexcept {
307 return SB(Min, typename SB::skip_validation());
308 }
309 constexpr static SB min() noexcept {
310 return SB(Min, typename SB::skip_validation());
311 }
312 constexpr static SB max() noexcept {
313 return SB(Max, typename SB::skip_validation());
314 }
315 };
316
317 } // std
318
319 #if BOOST_CLANG==1
320 #pragma GCC diagnostic pop
321 #endif
322
323 #endif // BOOST_NUMERIC_SAFE_BASE_HPP