From 014969690bed06d77cc2e08efbd2dc9b71fb0cd2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 16:04:15 -0700
Subject: [PATCH] shuffled things around to get MSVC optimizer to generate
 optimal code in particular, created shortcut overloads for conversions and
 moved comparison operators into member functions

---
 indra/llcommon/llunittype.h | 445 ++++++++++++++++++++----------------
 1 file changed, 253 insertions(+), 192 deletions(-)

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 949e4492c7a..a5e99070b6b 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -75,10 +75,10 @@ struct LLResultTypePromote
 	typedef LL_TYPEOF((true) ? S() : T()) type_t;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
+template<typename STORAGE_TYPE, typename UNITS>
 struct LLUnit
 {
-	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
+	typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
@@ -87,55 +87,55 @@ struct LLUnit
 	{}
 
 	// unit initialization and conversion
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	:	mValue(convert(other).mValue)
 	{}
 	
-	storage_t value() const
+	LL_FORCE_INLINE storage_t value() const
 	{
 		return mValue;
 	}
 
-	void value(storage_t value)
+	LL_FORCE_INLINE void value(storage_t value)
 	{
 		mValue = value;
 	}
 
-	template<typename NEW_UNIT_TYPE> 
+	template<typename NEW_UNITS> 
 	storage_t valueInUnits()
 	{
-		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value();
+		return LLUnit<storage_t, NEW_UNITS>(*this).value();
 	}
 
-	template<typename NEW_UNIT_TYPE> 
+	template<typename NEW_UNITS> 
 	void valueInUnits(storage_t value)
 	{
-		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
+		*this = LLUnit<storage_t, NEW_UNITS>(value);
 	}
 
-	void operator += (self_t other)
+	LL_FORCE_INLINE void operator += (self_t other)
 	{
 		mValue += convert(other).mValue;
 	}
 
-	void operator -= (self_t other)
+	LL_FORCE_INLINE void operator -= (self_t other)
 	{
 		mValue -= convert(other).mValue;
 	}
 
-	void operator *= (storage_t multiplicand)
+	LL_FORCE_INLINE void operator *= (storage_t multiplicand)
 	{
 		mValue *= multiplicand;
 	}
 
-	void operator *= (self_t multiplicand)
+	LL_FORCE_INLINE void operator *= (self_t multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
 	}
 
-	void operator /= (storage_t divisor)
+	LL_FORCE_INLINE void operator /= (storage_t divisor)
 	{
 		mValue /= divisor;
 	}
@@ -146,11 +146,58 @@ struct LLUnit
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
 	}
 
-	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
-	LL_FORCE_INLINE static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue == convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue != convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue < convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue <= convert(other).value();
+	}
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue > convert(other).value();
+	}
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue >= convert(other).value();
+	}
+
+	LL_FORCE_INLINE static self_t convert(self_t v) 
 	{ 
-		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
-		LLUnit<result_storage_t, UNIT_TYPE> result;
+		return v;
+	}
+
+	template<typename FROM_STORAGE_TYPE>
+	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v) 
+	{
+		self_t result;
+		result.mValue = (STORAGE_TYPE)v.value();
+		return result;
+	}
+
+	template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
+	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v) 
+	{ 
+		typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
+		LLUnit<result_storage_t, UNITS> result;
 		result_storage_t divisor = ll_convert_units(v, result);
 		result.value(result.value() / divisor);
 		return self_t(result.value());
@@ -160,15 +207,15 @@ struct LLUnit
 	storage_t mValue;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
 {
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        s << unit.value() << UNITS::getUnitLabel();
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
 {
         STORAGE_TYPE val;
         s >> val;
@@ -176,68 +223,145 @@ std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 {
-	typedef LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> self_t;
-	typedef typename LLUnit<STORAGE_TYPE, UNIT_TYPE>::storage_t storage_t;
-	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> base_t;
+	typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
+	typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
+	typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
 
-	LLUnitImplicit(storage_t value = storage_t())
+	LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
 	:	base_t(value)
 	{}
 
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	:	base_t(other)
 	{}
 
 	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
 	// this allows for interoperability with legacy code
-	operator storage_t() const
+	LL_FORCE_INLINE operator storage_t() const
 	{
 		return base_t::value();
 	}
 
 	using base_t::operator +=;
-	void operator += (storage_t value)
+	LL_FORCE_INLINE void operator += (storage_t value)
 	{
         base_t::mValue += value;
 	}
 
 	// this overload exists to explicitly catch use of another implicit unit
 	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	{
         base_t::mValue += convert(other).value();
 	}
 
 	using base_t::operator -=;
-	void operator -= (storage_t value)
+	LL_FORCE_INLINE void operator -= (storage_t value)
 	{
         base_t::mValue -= value;
 	}
 
 	// this overload exists to explicitly catch use of another implicit unit
 	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	{
         base_t::mValue -= convert(other).value();
 	}
 
+	using base_t::operator ==;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue == convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator == (STORAGE_T other)
+	{
+		return mValue == other;
+	}
+
+	using base_t::operator !=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue != convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator != (STORAGE_T other)
+	{
+		return mValue != other;
+	}
+	
+	using base_t::operator <;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue < convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator < (STORAGE_T other)
+	{
+		return mValue < other;
+	}
+
+	using base_t::operator <=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue <= convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator <= (STORAGE_T other)
+	{
+		return mValue <= other;
+	}
+
+	using base_t::operator >;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue > convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator > (STORAGE_T other)
+	{
+		return mValue > other;
+	}
+
+	using base_t::operator >=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue >= convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator >= (STORAGE_T other)
+	{
+		return mValue >= other;
+	}
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
 {
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        s << unit.value() << UNITS::getUnitLabel();
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
 {
         STORAGE_TYPE val;
         s >> val;
@@ -283,8 +407,8 @@ struct LLStorageType
 	typedef T type_t;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
 {
 	typedef STORAGE_TYPE type_t;
 };
@@ -296,65 +420,65 @@ struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
 //
 // operator +
 //
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+	result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
-	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
+	type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
 	result += second;
 	return result;
 }
@@ -362,64 +486,64 @@ LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::t
 //
 // operator -
 //
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+	result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
 	result -= second;
 	return result;
 }
@@ -427,44 +551,44 @@ LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYP
 //
 // operator *
 //
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
+	return LLUnit<STORAGE_TYPE1, UNITS1>();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second);
+	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
-	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2>)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
+	return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
 }
 
 
@@ -472,105 +596,42 @@ LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYP
 // operator /
 //
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
 	return first.value() / first.convert(second).value();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-//
-// comparison operators
-//
-
-#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)       \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \
-{                                                                                                                          \
-	return first.value() op second;                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \
-{                                                                                                                          \
-	return first op second.value();                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)                       \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}
-
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(==);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=);
-
-
 template<typename T> 
 struct LLGetUnitLabel
 {
-- 
GitLab