Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:59:43

0001 #ifndef BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
0002 #define BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP
0003 
0004 //  Copyright (c) 2012 Robert Ramey
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #include <cstdint> // for intmax_t/uintmax_t
0011 #include <iosfwd>
0012 #include <type_traits> // conditional, enable_if
0013 #include <boost/mp11/utility.hpp>
0014 
0015 #include "utility.hpp"
0016 #include "safe_integer.hpp"
0017 #include "checked_integer.hpp"
0018 
0019 namespace boost {
0020 namespace safe_numerics {
0021 
0022 template<typename T, T N, class P, class E>
0023 class safe_literal_impl;
0024 
0025 template<typename T, T N, class P, class E>
0026 struct is_safe<safe_literal_impl<T, N, P, E> > : public std::true_type
0027 {};
0028 
0029 template<typename T, T N, class P, class E>
0030 struct get_promotion_policy<safe_literal_impl<T, N, P, E> > {
0031     using type = P;
0032 };
0033 
0034 template<typename T, T N, class P, class E>
0035 struct get_exception_policy<safe_literal_impl<T, N, P, E> > {
0036     using type = E;
0037 };
0038 template<typename T, T N, class P, class E>
0039 struct base_type<safe_literal_impl<T, N, P, E> > {
0040     using type = T;
0041 };
0042 
0043 template<typename T, T N, class P, class E>
0044 constexpr T base_value(
0045     const safe_literal_impl<T, N, P, E> &
0046 ) {
0047     return N;
0048 }
0049 
0050 template<typename CharT, typename Traits, typename T, T N, class P, class E>
0051 inline std::basic_ostream<CharT, Traits> & operator<<(
0052     std::basic_ostream<CharT, Traits> & os,
0053     const safe_literal_impl<T, N, P, E> &
0054 ){
0055     return os << (
0056         (std::is_same<T, signed char>::value
0057         || std::is_same<T, unsigned char>::value
0058         ) ?
0059             static_cast<int>(N)
0060         :
0061             N
0062     );
0063 }
0064 
0065 template<typename T, T N, class P, class E>
0066 class safe_literal_impl {
0067 
0068     template<
0069         class CharT,
0070         class Traits
0071     >
0072     friend std::basic_ostream<CharT, Traits> & operator<<(
0073         std::basic_ostream<CharT, Traits> & os,
0074         const safe_literal_impl &
0075     ){
0076         return os << (
0077             (::std::is_same<T, signed char>::value
0078             || ::std::is_same<T, unsigned char>::value
0079             || ::std::is_same<T, wchar_t>::value
0080             ) ?
0081                 static_cast<int>(N)
0082             :
0083                 N
0084         );
0085     };
0086 
0087 public:
0088 
0089     ////////////////////////////////////////////////////////////
0090     // constructors
0091     // default constructor
0092     constexpr safe_literal_impl(){}
0093 
0094     /////////////////////////////////////////////////////////////////
0095     // casting operators for intrinsic integers
0096     // convert to any type which is not safe.  safe types need to be
0097     // excluded to prevent ambiguous function selection which
0098     // would otherwise occur
0099     template<
0100         class R,
0101         typename std::enable_if<
0102             ! boost::safe_numerics::is_safe<R>::value,
0103             int
0104         >::type = 0
0105     >
0106     constexpr operator R () const {
0107         // if static values don't overlap, the program can never function
0108         #if 1
0109         constexpr const interval<R> r_interval;
0110         static_assert(
0111             ! r_interval.excludes(N),
0112             "safe type cannot be constructed with this type"
0113         );
0114         #endif
0115 
0116         return validate_detail<
0117             R,
0118             std::numeric_limits<R>::min(),
0119             std::numeric_limits<R>::max(),
0120             E
0121         >::return_value(*this);
0122     }
0123 
0124     // non mutating unary operators
0125     constexpr safe_literal_impl<T, N, P, E> operator+() const { // unary plus
0126         return safe_literal_impl<T, N, P, E>();
0127     }
0128     // after much consideration, I've permitted the resulting value of a unary
0129     // - to change the type in accordance with the promotion policy.
0130     // The C++ standard does invoke integral promotions so it's changing the type as well.
0131 
0132     /*  section 5.3.1 &8 of the C++ standard
0133     The operand of the unary - operator shall have arithmetic or unscoped
0134     enumeration type and the result is the negation of its operand. Integral
0135     promotion is performed on integral or enumeration operands. The negative
0136     of an unsigned quantity is computed by subtracting its value from 2n,
0137     where n is the number of bits in the promoted operand. The type of the
0138     result is the type of the promoted operand.
0139     */
0140     template<
0141         typename Tx, Tx Nx, typename = std::enable_if_t<! checked::minus(Nx).exception()>
0142     >
0143     constexpr auto minus_helper() const {
0144         return safe_literal_impl<Tx, -N, P, E>();
0145     }
0146 
0147     constexpr auto operator-() const { // unary minus
0148         return minus_helper<T, N>();
0149     }
0150 
0151     /*   section 5.3.1 &10 of the C++ standard
0152     The operand of ~ shall have integral or unscoped enumeration type; 
0153     the result is the ones’ complement of its operand. Integral promotions 
0154     are performed. The type of the result is the type of the promoted operand.
0155     constexpr safe_literal_impl<T, checked::bitwise_not(N), P, E> operator~() const { // invert bits
0156         return safe_literal_impl<T, checked::bitwise_not(N), P, E>();
0157     }
0158     */
0159     template<
0160         typename Tx, Tx Nx, typename = std::enable_if_t<! checked::bitwise_not(Nx).exception()>
0161     >
0162     constexpr auto not_helper() const {
0163         return safe_literal_impl<Tx, ~N, P, E>();
0164     }
0165 
0166     constexpr auto operator~() const { // unary minus
0167         return not_helper<T, N>();
0168     }
0169 };
0170 
0171 template<
0172     std::intmax_t N,
0173     class P = void,
0174     class E = void
0175 >
0176 using safe_signed_literal = safe_literal_impl<
0177     typename utility::signed_stored_type<N, N>,
0178     N,
0179     P,
0180     E
0181 >;
0182 
0183 template<
0184     std::uintmax_t N,
0185     class P = void,
0186     class E = void
0187 >
0188 using safe_unsigned_literal = safe_literal_impl<
0189     typename utility::unsigned_stored_type<N, N>,
0190     N,
0191     P,
0192     E
0193 >;
0194 
0195 template<
0196     class T,
0197     T N,
0198     class P = void,
0199     class E = void,
0200     typename std::enable_if<
0201         std::is_signed<T>::value,
0202         int
0203     >::type = 0
0204 >
0205 constexpr auto make_safe_literal_impl() {
0206     return boost::safe_numerics::safe_signed_literal<N, P, E>();
0207 }
0208 
0209 template<
0210     class T,
0211     T N,
0212     class P = void,
0213     class E = void,
0214     typename std::enable_if<
0215         ! std::is_signed<T>::value,
0216         int
0217     >::type = 0
0218 >
0219 constexpr auto inline make_safe_literal_impl() {
0220     return boost::safe_numerics::safe_unsigned_literal<N, P, E>();
0221 }
0222 
0223 } // safe_numerics
0224 } // boost
0225 
0226 #define make_safe_literal(n, P, E)  \
0227     boost::safe_numerics::make_safe_literal_impl<decltype(n), n, P, E>()
0228 
0229 /////////////////////////////////////////////////////////////////
0230 // numeric limits for safe_literal etc.
0231 
0232 #include <limits>
0233 
0234 namespace std {
0235 
0236 template<
0237     typename T,
0238     T N,
0239     class P,
0240     class E
0241 >
0242 class numeric_limits<boost::safe_numerics::safe_literal_impl<T, N, P, E> >
0243     : public std::numeric_limits<T>
0244 {
0245     using SL = boost::safe_numerics::safe_literal_impl<T, N, P, E>;
0246 public:
0247     constexpr static SL lowest() noexcept {
0248         return SL();
0249     }
0250     constexpr static SL min() noexcept {
0251         return SL();
0252     }
0253     constexpr static SL max() noexcept {
0254         return SL();
0255     }
0256 };
0257 
0258 } // std
0259 
0260 #endif // BOOST_NUMERIC_SAFE_INTEGER_LITERAL_HPP