summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-08-27 16:04:15 -0700
committerRichard Linden <none@none>2013-08-27 16:04:15 -0700
commit014969690bed06d77cc2e08efbd2dc9b71fb0cd2 (patch)
treea32614f4df6b132b31f8ccfdf19593ee35813953
parent9dbc3b50a4fe0e5196855ab5b16ec6af7cafa337 (diff)
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
-rw-r--r--indra/llcommon/llunittype.h445
1 files changed, 253 insertions, 192 deletions
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 949e4492c7..a5e99070b6 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 @@ protected:
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
{