|
Boost : |
From: Jan Langer (jan_at_[hidden])
Date: 2004-01-17 10:21:10
Deane Yang wrote:
>>> Is there an intent for any of these proposed dimensional and unit
>>> libraries to restrict the types of operations being performed
>>> according to
>>> the scale of measurement that the unit belongs to? e.g. 10 kelvins / 5
>>> kelvins gives 2 kelvins, but 10 degrees Celsius / 5 degrees Celsius
>>> gives
>>> not only 2 degrees Celsius but also a compiler warning? :-) (An error
>>> would be too severe -- it's pretty common for social scientists to take
>>> means of ordinal data.)
>
> As I've mentioned before, one simply needs to distinguish between
> absolute temperature measurements (even in kelvins) and
> relative temperature measurements (representing the difference between
> two absolute temperatures).
>
> Why even in kelvins? Two reasons:
> 1) For temperature differences, degrees Celsius should be regarded
> as being identical to degrees Kelvin
> 2) Temperature differences in degrees Kelvin are allowed to be negative.
> Absolute temperature in degrees Kelvin is not.
i still think this issue should not be dealt with by means of the core
dimensions lib. so i typed a little class which should be able to
restrict the operations allowed on absolute and relative values.
since all operations are allowed on relative types, there is imho no
need of a distinct type for them.
normally something like this could be plugged into the dimensions lib
and everything could work as expected:
typedef ... kelvin;
absolute <kelvin> freezing_point (273.15);
absolute <kelvin> boiling_point = freezing_point + 100 * kelvin;
kelvin temp_diff = boiling_point - freezing_point;
freezing_point + boiling_point; // error
a similar approach should imho be followed to support the affine and
non-linear measures.
jan
-- jan langer ... jan_at_[hidden] "pi ist genau drei"
#include <cassert>
template <typename T>
class absolute
{
T value_;
public:
typedef T value_type;
absolute () : value_ (T ()) {}
template <typename S>
explicit absolute (S const &s)
: value_ (s) {}
template <typename S>
absolute (absolute <S> const &a)
: value_ (a.value ()) {}
template <typename S>
absolute &operator = (absolute <S> const &a)
{
value_ = a.value ();
return *this;
}
#define ARITH_ASSIGN_OP(SYMBOL) \
template <typename S> \
absolute &operator SYMBOL##= (S const &s) \
{ \
value_ SYMBOL##= s; \
return *this; \
}
ARITH_ASSIGN_OP(+)
ARITH_ASSIGN_OP(-)
ARITH_ASSIGN_OP(*)
ARITH_ASSIGN_OP(/)
#undef ARITH_ASSIGN_OP
absolute &operator ++ ()
{
++value_;
return *this;
}
absolute operator ++ (int)
{
absolute tmp (*this);
++*this;
return tmp;
}
absolute &operator -- ()
{
--value_;
return *this;
}
absolute operator -- (int)
{
absolute tmp (*this);
--*this;
return tmp;
}
T value () const
{ return value_; }
};
template <typename T>
absolute <T> make_absolute (T const &t)
{
return absolute <T> (t);
}
#define COMPARE_OP(SYMBOL) \
template <typename T, typename S> \
bool operator SYMBOL (absolute <T> const &a1, absolute <S> const &a2) \
{ \
return a1.value () SYMBOL a2.value (); \
}
COMPARE_OP(==)
COMPARE_OP(!=)
COMPARE_OP(>=)
COMPARE_OP(<=)
COMPARE_OP(>)
COMPARE_OP(<)
#undef COMPARE_OP
// the return type of the following operators
// actually needs to
// return typeof (T () SYMBOL S ())
// or something similar
#define ARITH_LEFT_OP(SYMBOL) \
template <typename T, typename S> \
absolute <T> \
operator SYMBOL (absolute <T> const &a1, S const &s2) \
{ \
return make_absolute (a1.value () SYMBOL s2); \
}
#define ARITH_RIGHT_OP(SYMBOL) \
template <typename T, typename S> \
absolute <S> \
operator SYMBOL (T const &t1, absolute <S> const &a2) \
{ \
return make_absolute (t1 SYMBOL a2.value ()); \
}
#define ARITH_BOTH_OP(SYMBOL) \
template <typename T, typename S> \
T \
operator SYMBOL (absolute <T> const &a1, absolute <S> const &a2) \
{ \
return a1.value () SYMBOL a2.value (); \
}
ARITH_LEFT_OP(+)
ARITH_RIGHT_OP(+)
ARITH_LEFT_OP(-)
ARITH_BOTH_OP(-)
ARITH_LEFT_OP(*)
ARITH_RIGHT_OP(*)
ARITH_LEFT_OP(/)
ARITH_BOTH_OP(/)
#undef ARITH_LEFT_OP
#undef ARITH_RIGHT_OP
#undef ARITH_BOTH_OP
template <typename T, typename S>
T
operator % (absolute <T> const &a1, S const &s2)
{
return a1.value () % s2;
}
int main ()
{
absolute <double> const C0 (0);
absolute <double> const C1 (1);
absolute <double> const C4 (4);
absolute <double> const C5 (5);
absolute <double> const C20 (20);
assert (make_absolute (20) == C20);
assert (C4 + 16 == C20);
assert (16 + C4 == C20);
assert (C20 - 16 == C4);
assert (C20 - C4 == 16);
assert (C4 * 5 == C20);
assert (5 * C4 == C20);
assert (C20 / 5 == C4);
assert (C20 / C4 == 5);
assert (C20 % 5 == 0);
assert (C0 != C20);
assert (C0 <= C20);
assert (C20 <= C20);
assert (C0 < C20);
assert (C20 >= C0);
assert (C20 >= C20);
assert (C20 > C0);
absolute <double> c = C4;
assert (c == C4);
assert (++c == C5);
assert (c == C5);
assert (--c == C4);
assert (c == C4);
assert (c++ == C4);
assert (c == C5);
assert (c-- == C5);
assert (c == C4);
// iterator over range
double i = 0;
for (absolute <double> c = C0; c <= C20; ++c, ++i)
assert (c.value () == i);
// take mean
{
absolute <double> s = C0;
for (absolute <double> c = C1; c <= C5; ++c)
s += c - C0;
s /= C5 - C1 + 1;
assert (s == make_absolute (3));
}
assert (C20.value () == 20);
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk