⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 safeint.hpp

📁 自定义HttpClient类
💻 HPP
📖 第 1 页 / 共 5 页
字号:
			throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);
		}
		++m_int;
		return *this;
	}
	
	//prefix decrement operator
	SafeInt<T>& operator --()
	{
		if(m_int == MinInt())
		{
			throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);
		}
		--m_int;
		return *this;
	}

	//postfix increment operator
	SafeInt<T> operator ++(int) //dummy arg to comply with spec
	{
		if(m_int == MaxInt())
		{
			throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);
		}

		SafeInt<T> tmp = m_int;

		m_int++;
		return tmp;
	}

	//postfix decrement operator
	SafeInt<T> operator --(int) //dummy arg to comply with spec
	{
		if(m_int == MinInt())
		{
			throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);
		}

		SafeInt<T> tmp = m_int;
		m_int--;
		return tmp;
	}

	//one's complement
	//note - this operator will normally change size to an int
	//cast in return improves perf and maintains type
	SafeInt<T> operator ~() const {return SafeInt<T>((T)~m_int);}

	//binary operators
	//
	// arithmetic binary operators
	// % modulus
	// * multiplication
	// / division
	// + addition
	// - subtraction
	//
	// For each of the arithmetic operators, you will need to 
	// use them as follows:
	//
	// SafeInt<char> c = 2;
	// SafeInt<int>  i = 3;
	//
	// SafeInt<int> i2 = i op c.Value();
	// OR
	// SafeInt<char> i2 = i.Value() op c;
	//
	// The base problem is that if the lhs and rhs inputs are different SafeInt types
	// it is not possible in this implementation to determine what type of SafeInt
	// should be returned. You have to let the class know which of the two inputs
	// need to be the return type by forcing the other value to the base integer type.
	// The case of:
	//
	// SafeInt<T> i, j, k;
	// i = j op k;
	//
	// works just fine and no unboxing is needed because the return type is not ambiguous.

	//modulus
	//modulus has some convenient properties - 
	//first, the magnitude of the return can never be
	//larger than the lhs operand, and it must be the same sign
	//as well. It does, however, suffer from the same promotion
	//problems as comparisons, division and other operations
	template <typename U>
	SafeInt<T> operator %(U rhs)
	{
		return MixedSizeModulus(*this, rhs);
	}

	SafeInt<T> operator %(SafeInt<T> rhs)
	{
		if(rhs.Value() == 0)
			throw SafeIntException(EXCEPTION_INT_DIVIDE_BY_ZERO);

		//this is always safe
		return SafeInt<T>((T)(m_int % rhs.Value()));
	}

	//modulus assignment
	template <typename U>
	SafeInt<T>& operator %=(U rhs)
	{
		*this = MixedSizeModulus(*this, rhs);
		return *this;
	}

	template <typename U>
	SafeInt<T>& operator %=(SafeInt<U> rhs)
	{
		*this = MixedSizeModulus(*this, rhs.Value());
		return *this;
	}

	//multiplication
	template <typename U>
	SafeInt<T> operator *(U rhs)
	{
		return MixedSizeMultiply(*this, rhs);
	}

	SafeInt<T> operator *(SafeInt<T> rhs)
	{
		return SafeInt<T>(multiply(m_int, rhs.Value()));
	}

	//multiplication assignment
	SafeInt<T>& operator *=(SafeInt<T> rhs)
	{
		m_int = multiply(rhs.m_int, m_int);
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator *=(U rhs)
	{
		*this = MixedSizeMultiply(*this, rhs);
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator *=(SafeInt<U> rhs)
	{
		*this = MixedSizeMultiply(*this, rhs.Value());
		return *this;
	}

	//division
	template <typename U>
	SafeInt<T> operator /(U rhs)
	{
		return MixedSizeDivision(*this, rhs);
	}

	SafeInt<T> operator /(SafeInt<T> rhs)
	{
		return MixedSizeDivision(*this, rhs.Value());
	}

	//division assignment
	SafeInt<T>& operator /=(SafeInt<T> i)
	{
		*this = MixedSizeDivision(*this, i.Value());
		return *this;
	}

	template <typename U> SafeInt<T>& operator /=(U i)
	{
		*this = MixedSizeDivision(*this, i);
		return *this;
	}

	template <typename U> SafeInt<T>& operator /=(SafeInt<U> i)
	{
		*this = MixedSizeDivision(*this, i.Value());
		return *this;
	}

	//for addition and subtraction

	//addition
	inline SafeInt<T> operator +(SafeInt<T> rhs)
	{
		return SafeInt<T>(addition(m_int, rhs.Value()));
	}

	template <typename U>
	inline SafeInt<T> operator +(U rhs)
	{
		return MixedSizeAddition(*this, rhs);
	}

	//addition assignment
	SafeInt<T>& operator +=(SafeInt<T> rhs)
	{
		m_int = addition(m_int, rhs.m_int);
		return *this;
	}

	template <typename U>
	SafeInt<T>& operator +=(U rhs)
	{
		*this = MixedSizeAddition(*this, rhs);
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator +=(SafeInt<U> rhs)
	{
		*this = MixedSizeAddition(*this, rhs.Value());
		return *this;
	}

	//subtraction
	template <typename U>
	SafeInt<T> operator -(U rhs)
	{
		return MixedSizeSubtraction(*this, rhs);
	}

	SafeInt<T> operator -(SafeInt<T> rhs)
	{
		return SafeInt<T>(subtraction(m_int, rhs.m_int));
	}

	//subtraction assignment
	SafeInt<T>& operator -=(SafeInt<T> rhs)
	{
		m_int = subtraction(m_int, rhs.m_int);
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator -=(U rhs)
	{
		*this = MixedSizeSubtraction(*this, rhs);
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator -=(SafeInt<U> rhs)
	{
		*this = MixedSizeSubtraction(*this, rhs.Value());
		return *this;
	}

	//comparison operators
	//additional overloads defined outside the class at the bottom of
	//the header to allow for cases where the SafeInt is the rhs value

	// less than
	template <typename U>
	bool operator <(U rhs)
	{
		return LessThan(m_int, rhs);
	}

	bool operator <(SafeInt<T> rhs)
	{
		return m_int < rhs.m_int;
	}

	//greater than or eq.
	template <typename U>
	bool operator >=(U rhs){return !(*this < rhs);}

	bool operator >=(SafeInt<T> rhs)
	{
		return m_int >= rhs.Value();
	}

	// greater than
	template <typename U>
	bool operator >(U rhs)
	{
		return SafeInt<T>::GreaterThan(m_int, rhs);
	}

	bool operator >(SafeInt<T> rhs)
	{
		return m_int > rhs.m_int;
	}

	//less than or eq.
	template <typename U>
	bool operator <=(U rhs){return !(*this > rhs);}

	//same type - easy path
	bool operator <=(SafeInt<T> rhs)
	{
		return m_int <= rhs.Value();
	}

	//equality
	template <typename U>
	bool operator ==(U rhs){return Equals(m_int, rhs);}

	//need an explicit override for type bool
	bool operator ==(bool rhs)
	{
		return (m_int == 0 ? false : true) == rhs;
	}

	bool operator ==(SafeInt<T> rhs){return m_int == rhs.Value();}

	//!= operators
	template <typename U>
	bool operator !=(U rhs){return !Equals(m_int, rhs);}

	bool operator !=(bool b)
	{
		return (m_int == 0 ? false : true) != b;
	}

	bool operator !=(SafeInt<T> rhs){return m_int != rhs.Value();}

	//shift operators
	//Note - shift operators ALWAYS return the same type as the lhs
	//specific version for SafeInt<T> not needed - 
	//code path is exactly the same as for SafeInt<U> as rhs

	//left shift
	//Also, shifting > bitcount is undefined - trap in debug
	template <typename U> 
	SafeInt<T> operator <<(U bits)
	{
		if(IsSigned(bits))
            assert(bits >= 0);

		assert(bits < BitCount());

		return SafeInt<T>((T)(m_int << bits));
	}

	template <typename U> 
	SafeInt<T> operator <<(SafeInt<U> bits)
	{
		if(IsSigned(bits))
            assert(bits >= 0);

		assert(bits < BitCount());

		return SafeInt<T>((T)(m_int << bits.Value()));
	}

	//left shift assignment

	template <typename U>
	SafeInt<T>& operator <<=(U bits)
	{
		if(IsSigned(bits))
			assert(bits >= 0);

		assert(bits < BitCount());

		m_int <<= bits;
		return *this;
	}

	template <typename U>
	SafeInt<T>& operator <<=(SafeInt<U> bits)
	{
		if(IsSigned(bits))
			assert(bits.Value() >= 0);

		assert(bits.Value() < BitCount());

		m_int <<= bits.Value();
		return *this;
	}

	//right shift
	template <typename U> 
	SafeInt<T> operator >>(U bits)
	{
		if(IsSigned(bits))
            assert(bits >= 0);

		assert(bits < BitCount());

		return SafeInt<T>((T)(m_int >> bits));
	}

	template <typename U> 
	SafeInt<T> operator >>(SafeInt<U> bits)
	{
		if(IsSigned(bits))
            assert(bits >= 0);

		assert(bits < BitCount());

		return SafeInt<T>((T)(m_int >> bits.Value()));
	}

	//right shift assignment
	template <typename U>
	SafeInt<T>& operator >>=(U bits)
	{
		if(IsSigned(bits))
			assert(bits >= 0);

		assert(bits < BitCount());

		m_int >>= bits;
		return *this;
	}

	template <typename U>
	SafeInt<T>& operator >>=(SafeInt<U> bits)
	{
		if(IsSigned(bits))
			assert(bits.Value() >= 0);

		assert(bits.Value() < BitCount());

		m_int >>= bits.Value();
		return *this;
	}

	//bitwise operators
	//this only makes sense if we're dealing with the same type and size
	//demand a type T, or something that fits into a type T

	//bitwise &
	SafeInt<T> operator &(SafeInt<T> rhs)
	{
		return SafeInt<T>((T)(m_int & rhs.m_int));
	}

	template <typename U>
	SafeInt<T> operator &(U rhs)
	{
		//if U can fit into T without truncating, force U to T
		if(sizeof(U) <= sizeof(T))
			return SafeInt<T>(m_int & (T)rhs);

		//might still be safe
		//cast rhs down to a T, then back up to U
		//check to see if it is equal to the original value
		//this allows things like
		//SafeInt<char>(2) & 4 (literal is an int) to work
		if( (U)((T)rhs) == rhs)
			return SafeInt<T>(m_int & (T)rhs);
		
		throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);

	}

	//bitwise & assignment
	SafeInt<T>& operator &=(SafeInt<T> rhs)
	{
		m_int &= rhs.m_int;
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator &=(U rhs)
	{
		*this = *this & rhs;
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator &=(SafeInt<U> rhs)
	{
		*this = *this & rhs.Value();
		return *this;
	}

	//XOR
	SafeInt<T> operator ^(SafeInt<T> rhs)
	{
		return SafeInt<T>((T)(m_int ^ rhs.m_int));
	}

	template <typename U>
	SafeInt<T> operator ^(U rhs)
	{
		//if U can fit into T without truncating, force U to T
		if(sizeof(U) <= sizeof(T))
			return SafeInt<T>(m_int ^ (T)rhs);
		
		if( (U)((T)rhs) == rhs)
			return SafeInt<T>(m_int ^ (T)rhs);

		throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW);

	}

	//XOR assignment
	SafeInt<T>& operator ^=(SafeInt<T> i)
	{
		m_int ^= i.m_int;
		return *this;
	}

	template <typename U> 
	SafeInt<T>& operator ^=(U rhs)
	{
		*this = *this ^ rhs;
		return *this;
	}

	template <typename U> 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -