Class integer

Synopsis

#include <include/type_safe/integer.hpp>

template <typename IntegerT, class Policy /* = arithmetic_policy_default*/>
class integer

Description

A type safe integer class.

This is a tiny, no overhead wrapper over a standard integer type. It behaves exactly like the built-in types except that narrowing conversions are not allowed. It also checks against unsigned under/overflow in debug mode and marks it as undefined for the optimizer otherwise.

A conversion is considered safe if both integer types have the same signedness and the size of the value being converted is less than or equal to the destination size.

\requires IntegerT must be an integral type except bool and char (use signed char/unsigned char). \notes It intentionally does not provide the bitwise operations. \module types

Mentioned in

Methods

integer overload\effects Initializes it with the given value
integer overload\group constructor
get\group conversion
operator integer_typeReturns: The stored value as the native integer type
operator+Returns: The integer type unchanged.
operator++ overload\effects Increments the integer by one
operator++ overload\group increment
operator+=\effects Same as the operation on the integer type
operator-Returns: The negative integer type
operator-- overload\effects Decrements the integer by one
operator-- overload\group decrement
operator= overload\effects Assigns it with the given value
operator= overload\group assignment
TYPE_SAFE_DETAIL_MAKE_OP\group compound_assign

Source

Lines 96-311 in include/type_safe/integer.hpp.

template <typename IntegerT, class Policy /* = arithmetic_policy_default*/>
class integer
{
    static_assert(detail::is_integer<IntegerT>::value, "must be a real integer type");

public:
    using integer_type = IntegerT;

    //=== constructors ===//
#if TYPE_SAFE_DELETE_FUNCTIONS
    /// \exclude
    integer() = delete;
#endif

    /// \effects Initializes it with the given value.
    /// \notes This function does not participate in overload resolution
    /// if `T` is not an integer type safely convertible to this type.
    /// \group constructor
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE constexpr integer(const T& val) : value_(val)
    {}

    /// \group constructor
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE constexpr integer(const integer<T, Policy>& val)
    : value_(static_cast<T>(val))
    {}

#if TYPE_SAFE_DELETE_FUNCTIONS
    /// \exclude
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>
    constexpr integer(T) = delete;
    /// \exclude
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>
    constexpr integer(const integer<T, Policy>&) = delete;
#endif

    //=== assignment ===//
    /// \effects Assigns it with the given value.
    /// \notes This function does not participate in overload resolution
    /// if `T` is not an integer type safely convertible to this type.
    /// \group assignment
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator=(const T& val)
    {
        value_ = val;
        return *this;
    }

    /// \group assignment
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator=(const integer<T, Policy>& val)
    {
        value_ = static_cast<T>(val);
        return *this;
    }

#if TYPE_SAFE_DELETE_FUNCTIONS
    /// \exclude
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>
    constexpr integer(T) = delete;
    /// \exclude
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>
    integer& operator=(const integer<T, Policy>&) = delete;
#endif

    //=== conversion back ===//
    /// \returns The stored value as the native integer type.
    /// \group conversion
    TYPE_SAFE_FORCE_INLINE explicit constexpr operator integer_type() const noexcept
    {
        return value_;
    }

    /// \group conversion
    TYPE_SAFE_FORCE_INLINE constexpr integer_type get() const noexcept
    {
        return value_;
    }

    //=== unary operators ===//
    /// \returns The integer type unchanged.
    TYPE_SAFE_FORCE_INLINE constexpr integer operator+() const
    {
        return *this;
    }

    /// \returns The negative integer type.
    /// \requires The integer type must not be unsigned.
    TYPE_SAFE_FORCE_INLINE constexpr integer operator-() const
    {
        static_assert(std::is_signed<integer_type>::value,
                      "cannot call unary minus on unsigned integer");
        return integer(Policy::template do_multiplication(value_, integer_type(-1)));
    }

    /// \effects Increments the integer by one.
    /// \group increment
    TYPE_SAFE_FORCE_INLINE integer& operator++()
    {
        value_ = Policy::template do_addition(value_, integer_type(1));
        return *this;
    }

    /// \group increment
    TYPE_SAFE_FORCE_INLINE integer operator++(int)
    {
        auto res = *this;
        ++*this;
        return res;
    }

    /// \effects Decrements the integer by one.
    /// \group decrement
    TYPE_SAFE_FORCE_INLINE integer& operator--()
    {
        value_ = Policy::template do_subtraction(value_, integer_type(1));
        return *this;
    }

    /// \group decrement
    TYPE_SAFE_FORCE_INLINE integer operator--(int)
    {
        auto res = *this;
        --*this;
        return res;
    }

//=== compound assignment ====//
/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_OP(Op)                                                               \
    /** \group compound_assign                                                                     \
     * \param 1                                                                                    \
     * \exclude */                                                                                 \
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>      \
    TYPE_SAFE_FORCE_INLINE integer& operator Op(const T& other)                                    \
    {                                                                                              \
        return *this Op integer<T, Policy>(other);                                                 \
    }                                                                                              \
    /** \exclude */                                                                                \
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>    \
    integer& operator Op(integer<T, Policy>) = delete;                                             \
    /** \exclude */                                                                                \
    template <typename T, typename = detail::fallback_safe_integer_conversion<T, integer_type>>    \
    integer& operator Op(T) = delete;

    /// \effects Same as the operation on the integer type.
    /// \notes These functions do not participate in overload resolution,
    /// if `T` is not an integer type safely convertible to this type.
    /// \group compound_assign Compound assignment
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator+=(const integer<T, Policy>& other)
    {
        value_ = Policy::template do_addition<integer_type>(value_, static_cast<T>(other));
        return *this;
    }
    TYPE_SAFE_DETAIL_MAKE_OP(+=)

    /// \group compound_assign
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator-=(const integer<T, Policy>& other)
    {
        value_ = Policy::template do_subtraction<integer_type>(value_, static_cast<T>(other));
        return *this;
        return *this;
    }
    TYPE_SAFE_DETAIL_MAKE_OP(-=)

    /// \group compound_assign
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator*=(const integer<T, Policy>& other)
    {
        value_ = Policy::template do_multiplication<integer_type>(value_, static_cast<T>(other));
        return *this;
    }
    TYPE_SAFE_DETAIL_MAKE_OP(*=)

    /// \group compound_assign
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator/=(const integer<T, Policy>& other)
    {
        value_ = Policy::template do_division<integer_type>(value_, static_cast<T>(other));
        return *this;
    }
    TYPE_SAFE_DETAIL_MAKE_OP(/=)

    /// \group compound_assign
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_safe_integer_conversion<T, integer_type>>
    TYPE_SAFE_FORCE_INLINE integer& operator%=(const integer<T, Policy>& other)
    {
        value_ = Policy::template do_modulo<integer_type>(value_, static_cast<T>(other));
        return *this;
    }
    TYPE_SAFE_DETAIL_MAKE_OP(%=)

#undef TYPE_SAFE_DETAIL_MAKE_OP

private:





Add Discussion as Guest

Log in