Header file range/v3/utility/safe_int.hpp

#include <range/v3/range_fwd.hpp>

#include <range/v3/utility/concepts.hpp>

namespace ranges
{
    inline namespace v3
    {
        namespace detail
        {
            template <typename Signed>
            using unsigned_t = typename std::make_unsigned<Signed>::type;
            
            template <typename Signed>
            constexpr unsigned_t<Signed> abs(Signed i);
            
            template <typename Signed>
            constexpr unsigned_t<Signed> signbit(Signed i);
            
            template <typename Unsigned>
            constexpr Unsigned log2(Unsigned n, Unsigned p = 0);
            
            template <typename Signed>
            constexpr bool is_mult_safe(Signed left, Signed right);
            
            template <typename Signed>
            constexpr bool same_sign(Signed left, Signed right);
        }
        
        template <typename SignedInteger>
        struct safe_int
        {
            constexpr safe_int() = default;
            
            constexpr safe_int(SignedInteger i) noexcept;
            
            constexpr SignedInteger const_get() const noexcept;
            
            SignedInteger get() const noexcept;
            
            explicit operator SignedInteger() const noexcept;
            
            static constexpr safe_int inf() noexcept;
            
            static constexpr safe_int NaN() noexcept;
            
            constexpr bool is_finite() const noexcept;
            
            constexpr bool is_NaN() const noexcept;
            
            explicit constexpr operator bool() const;
            
            constexpr bool operator!() const;
            
            constexpr safe_int operator-() const noexcept;
            
            safe_int& operator++() noexcept;
            
            safe_int& operator++(int) noexcept;
            
            safe_int& operator--() noexcept;
            
            safe_int& operator--(int) noexcept;
            
            safe_int& operator+=(safe_int that);
            
            safe_int& operator-=(safe_int that);
            
            safe_int& operator/=(safe_int that);
            
            safe_int& operator%=(safe_int that);
            
            safe_int& operator*=(safe_int that);
        };
        
        template <typename Int>
        struct make_safe_int
        {
            using type = safe_int<typename std::make_signed<Int>::type>;
        };
        
        template <typename Int>
        struct make_safe_int<safe_int<Int>>
        {
            using type = safe_int<Int>;
        };
        
        template <typename Int>
        using make_safe_int_t = typename make_safe_int<Int>::type;
    }
}

namespace std{}