File indexing completed on 2025-01-18 09:51:36
0001 #ifndef BOOST_NUMERIC_SAFE_BASE_HPP
0002 #define BOOST_NUMERIC_SAFE_BASE_HPP
0003
0004
0005
0006
0007
0008
0009
0010 #include <limits>
0011 #include <type_traits> // is_integral, enable_if, conditional is_convertible
0012 #include <boost/config.hpp> // BOOST_CLANG
0013 #include "concept/exception_policy.hpp"
0014 #include "concept/promotion_policy.hpp"
0015
0016 #include "safe_common.hpp"
0017 #include "exception_policies.hpp"
0018
0019 #include "boost/concept/assert.hpp"
0020
0021 namespace boost {
0022 namespace safe_numerics {
0023
0024
0025
0026
0027
0028 template<
0029 class Stored,
0030 Stored Min,
0031 Stored Max,
0032 class P,
0033 class E
0034 >
0035 class safe_base;
0036
0037 template<
0038 class T,
0039 T Min,
0040 T Max,
0041 class P,
0042 class E
0043 >
0044 struct is_safe<safe_base<T, Min, Max, P, E> > : public std::true_type
0045 {};
0046
0047 template<
0048 class T,
0049 T Min,
0050 T Max,
0051 class P,
0052 class E
0053 >
0054 struct get_promotion_policy<safe_base<T, Min, Max, P, E> > {
0055 using type = P;
0056 };
0057
0058 template<
0059 class T,
0060 T Min,
0061 T Max,
0062 class P,
0063 class E
0064 >
0065 struct get_exception_policy<safe_base<T, Min, Max, P, E> > {
0066 using type = E;
0067 };
0068
0069 template<
0070 class T,
0071 T Min,
0072 T Max,
0073 class P,
0074 class E
0075 >
0076 struct base_type<safe_base<T, Min, Max, P, E> > {
0077 using type = T;
0078 };
0079
0080 template<
0081 class T,
0082 T Min,
0083 T Max,
0084 class P,
0085 class E
0086 >
0087 constexpr T base_value(
0088 const safe_base<T, Min, Max, P, E> & st
0089 ) {
0090 return static_cast<T>(st);
0091 }
0092
0093 template<
0094 typename T,
0095 T N,
0096 class P,
0097 class E
0098 >
0099 class safe_literal_impl;
0100
0101
0102 #if BOOST_CLANG==1
0103 #pragma GCC diagnostic push
0104 #pragma GCC diagnostic ignored "-Wmismatched-tags"
0105 #endif
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 template<
0117 class Stored,
0118 Stored Min,
0119 Stored Max,
0120 class P,
0121 class E
0122 >
0123 class safe_base {
0124 private:
0125 BOOST_CONCEPT_ASSERT((PromotionPolicy<P>));
0126 BOOST_CONCEPT_ASSERT((ExceptionPolicy<E>));
0127 Stored m_t;
0128
0129 template<class T>
0130 constexpr Stored validated_cast(const T & t) const;
0131
0132
0133
0134 template<class CharT, class Traits>
0135 void output(std::basic_ostream<CharT, Traits> & os) const;
0136
0137
0138
0139
0140
0141
0142
0143
0144 template<class CharT, class Traits>
0145 friend std::basic_ostream<CharT, Traits> &
0146 operator<<(
0147 std::basic_ostream<CharT, Traits> & os,
0148 const safe_base & t
0149 ){
0150 t.output(os);
0151 return os;
0152 }
0153
0154 template<class CharT, class Traits>
0155 void input(std::basic_istream<CharT, Traits> & is);
0156
0157
0158 template<class CharT, class Traits>
0159 friend inline std::basic_istream<CharT, Traits> &
0160 operator>>(
0161 std::basic_istream<CharT, Traits> & is,
0162 safe_base & t
0163 ){
0164 t.input(is);
0165 return is;
0166 }
0167
0168 public:
0169
0170
0171
0172 constexpr safe_base();
0173
0174 struct skip_validation{};
0175
0176 constexpr explicit safe_base(const Stored & rhs, skip_validation);
0177
0178
0179 template<
0180 class T,
0181 typename std::enable_if<
0182 std::is_convertible<T, Stored>::value,
0183 bool
0184 >::type = 0
0185 >
0186 constexpr safe_base(const T & t);
0187
0188
0189 template<typename T, T N, class Px, class Ex>
0190 constexpr safe_base(const safe_literal_impl<T, N, Px, Ex> & t);
0191
0192
0193
0194 ~safe_base() = default;
0195
0196 constexpr safe_base(const safe_base &) = default;
0197
0198 constexpr safe_base & operator=(const safe_base &) = default;
0199
0200 constexpr safe_base(safe_base &&) = default;
0201
0202 constexpr safe_base & operator=(safe_base &&) = default;
0203
0204
0205
0206
0207
0208
0209
0210 template<
0211 class R,
0212 typename std::enable_if<
0213 ! boost::safe_numerics::is_safe<R>::value,
0214 int
0215 >::type = 0
0216 >
0217 constexpr operator R () const;
0218
0219
0220
0221 template<class T>
0222 constexpr safe_base &
0223 operator=(const T & rhs){
0224 m_t = validated_cast(rhs);
0225 return *this;
0226 }
0227
0228
0229 constexpr safe_base & operator++(){
0230 return *this = *this + 1;
0231 }
0232 constexpr safe_base & operator--(){
0233 return *this = *this - 1;
0234 }
0235 constexpr safe_base operator++(int){
0236 safe_base old_t = *this;
0237 ++(*this);
0238 return old_t;
0239 }
0240 constexpr safe_base operator--(int){
0241 safe_base old_t = *this;
0242 --(*this);
0243 return old_t;
0244 }
0245
0246 constexpr auto operator+() const {
0247 return *this;
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 constexpr auto operator-() const {
0262
0263
0264
0265
0266
0267 return 0 - *this;
0268 }
0269
0270
0271
0272
0273
0274 constexpr auto operator~() const {
0275 return ~Stored(0u) ^ *this;
0276 }
0277 };
0278
0279 }
0280 }
0281
0282
0283
0284
0285 #include <limits>
0286
0287 namespace std {
0288
0289 template<
0290 class T,
0291 T Min,
0292 T Max,
0293 class P,
0294 class E
0295 >
0296 class numeric_limits<boost::safe_numerics::safe_base<T, Min, Max, P, E> >
0297 : public std::numeric_limits<T>
0298 {
0299 using SB = boost::safe_numerics::safe_base<T, Min, Max, P, E>;
0300 public:
0301 constexpr static SB lowest() noexcept {
0302 return SB(Min, typename SB::skip_validation());
0303 }
0304 constexpr static SB min() noexcept {
0305 return SB(Min, typename SB::skip_validation());
0306 }
0307 constexpr static SB max() noexcept {
0308 return SB(Max, typename SB::skip_validation());
0309 }
0310 };
0311
0312 }
0313
0314 #if BOOST_CLANG==1
0315 #pragma GCC diagnostic pop
0316 #endif
0317
0318 #endif