#ifndef DIM_HPP #define DIM_HPP #include #include #include #include #include #include #include #include #include namespace dim { #define DIM_BASE_UNITS \ (mass)(time)(length)(current)(temperature)(amount_of_substance)(intensity) \ /**/ #define SEQ DIM_BASE_UNITS #define M1(r, _, i, x) \ BOOST_PP_COMMA_IF(i) int x \ /**/ template struct dimensions { inline dimensions(void) { return; } #define M2(r, _, x) \ char (& BOOST_PP_CAT(x, _magnitude)(void) const)[1 + (x < 0 ? -x : x)]; \ char (& BOOST_PP_CAT(x, _sign)(void) const)[1 + (x < 0)]; \ /**/ BOOST_PP_SEQ_FOR_EACH(M2, ~, SEQ) #undef M2 }; #undef M1 const dimensions scalar; #define PRED(s, nss) BOOST_PP_SEQ_ELEM(0, nss) #define OP(s, nss) \ ( BOOST_PP_DEC(BOOST_PP_SEQ_ELEM(0, nss)) ) \ ( BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(1, nss))(0) ) \ ( BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_ELEM(2, nss))(0) ) \ /**/ #define MACRO(s, nss) \ const dimensions \ BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_ELEM(1, nss)); \ /**/ BOOST_PP_FOR( ( BOOST_PP_SEQ_SIZE(SEQ) ) ( BOOST_PP_SEQ_REVERSE(SEQ) ) ( BOOST_PP_SEQ_FOR_EACH((0) BOOST_PP_TUPLE_EAT(3), ~, BOOST_PP_SEQ_TAIL(SEQ))(1) ), PRED, OP, MACRO ) #undef PRED #undef OP #undef MACRO #define DEF(op1, op2, size) \ template \ dimensions \ operator op2(dimensions, dimensions); \ /**/ DEF(+, *, BOOST_PP_SEQ_SIZE(SEQ)) DEF(-, /, BOOST_PP_SEQ_SIZE(SEQ)) #undef DEF #undef SEQ // ------------------------------ // #define DIM(x) \ dim::dimensions< \ BOOST_PP_SEQ_FOR_EACH_I( \ DIM_PRIVATE, x, DIM_BASE_UNITS \ ) \ > \ /**/ #define DIM_PRIVATE(r, y, i, x) \ BOOST_PP_COMMA_IF(i) ((int)sizeof((y).BOOST_PP_CAT(x, _magnitude)()) - 1) * (sizeof((y).BOOST_PP_CAT(x, _sign)()) == 1 ? 1 : -1) \ /**/ // ------------------------------ // template class quantity { public: typedef D dimensions; inline quantity(T x) : x_(x) { return; } inline T value(void) const { return x_; } private: T x_; }; template inline quantity operator+(quantity x) { return x; } template inline quantity operator-(quantity x) { return -x.value(); } template inline quantity operator+(quantity x, quantity y) { return x.value() + y.value(); } template inline quantity operator-(quantity x, quantity y) { return x.value() - y.value(); } namespace hack { template struct multiply { typedef DIM(D1() * D2()) type; }; template struct divide { typedef DIM(D1() / D2()) type; }; } template inline quantity::type> operator*(quantity x, quantity y) { return x.value() * y.value(); } template inline quantity::type> operator/(quantity x, quantity y) { assert(y.value()); return x.value() / y.value(); } } #endif