分析模式-计量的C++实现——完美版本

    技术2022-05-11  120

    以下是http://www.csdn.net/develop/Article/14/14487.shtm的一个改进版本,本来是作为评论附在上一篇文章后面的,但是作为评论发表的话,会丢失很多文字,很奇怪的说。本文是我和singleracer讨论的结果,个人认为几乎接近完美,希望能对大家有帮助,大家可以自己加入其它的单位体系和单位。

    计量的模板类:

    #ifndef _QUANTITY_H_#define _QUANTITY_H_

    #ifdef _DEBUG#define ASSERT_SAME_TYPE( T1, T2) do {T1 v=T2();v; }while(false)#else#define ASSERT_SAME_TYPE( T1, T2)#endif

    #include "singleton.h"

    template<class UnitType>struct UnitTraits { typedef UnitType::Validator Validator;};

    template<class ValueType>class ValueTraits {public: static bool equal(const ValueType & l, const ValueType & r) {return (l == r);}};

    template<>class ValueTraits<double> {public: static bool equal(const double & l, const double & r) {  static double precision = 0.000000001;  return (l - r < precision); }};

    template<>class ValueTraits<float> {public: static bool equal(const float & l, const float & r) {  static float precision = 0.000000001f;  return (l - r < precision); }};

    template<typename ValueType, class UnitValidator, class _Traits = ValueTraits<ValueType> >class Quantity{public: typedef UnitValidator Validator;

     template<typename UnitType>Quantity(const ValueType & amount, const UnitType & )  : m_amount(amount), m_unit(Singleton< unit_wrap<UnitType, ValueType> >::Instance()) {  ASSERT_SAME_TYPE(UnitTraits<UnitType>::Validator, Validator); } ~Quantity() { } Quantity(const Quantity & other)  : m_amount(other.m_amount), m_unit(other.m_unit) { } Quantity & operator=(const Quantity & rhs) {  if(&rhs != this)  {   m_amount = rhs.m_amount;   m_unit = rhs.m_unit;  }  return *this; } template<typename UnitType> void convert(const UnitType & ) {  ASSERT_SAME_TYPE(UnitTraits<UnitType>::Validator, Validator);  unit_base<ValueType> * unit = Singleton< unit_wrap<UnitType, ValueType> >::Instance();  if(unit != m_unit)  {   m_amount = m_unit->to_standard(m_amount);   m_unit = unit;   m_amount = m_unit->from_standard(m_amount);  }

     } Quantity & operator+=(const Quantity & rhs) {  m_amount += unitize( rhs );  return *this; } Quantity & operator-=(const Quantity & rhs) {  m_amount -= unitize( rhs );  return *this; } bool operator==(const Quantity & rhs) {  return _Traits::equal( m_amount, unitize(rhs)); } bool operator>(const Quantity & rhs) {  return m_amount > unitize( rhs ); } bool operator>=(const Quantity & rhs) {  return (m_amount > unitize( rhs ) ? true : (equal( m_amount, unitize(rhs))) ); } bool operator<(const Quantity & rhs) {  return m_amount < unitize( rhs ); } bool operator<=(const Quantity & rhs) {  return (m_amount < unitize( rhs ) ? true : (equal( m_amount, unitize(rhs))) ); }

    private: // 对于单位相同的运算不需要转换,也就没有丢失精度的问题 ValueType unitize( const Quantity & rhs ) {  if( m_unit == rhs.m_unit )   return rhs.m_amount;  else   return m_unit->from_standard(rhs.m_unit->to_standard(rhs.m_amount)); }

    private: template<typename ValueType> class unit_base { public:  virtual ValueType to_standard(const ValueType & val) const = 0;  virtual ValueType from_standard(const ValueType & val) const = 0; }; // 把unit_wrap设计为singleton,这样比较单位是否相同只需作简单的指针比较 template<typename UnitType, typename ValueType> class unit_wrap : public unit_base<ValueType> {protected: unit_wrap() {} ~unit_wrap() {} public:  virtual ValueType to_standard(const ValueType & val) const  {   return UnitType::to_standard(val);  }  virtual ValueType from_standard(const ValueType & val) const  {   return UnitType::from_standard(val);  } };

    private: ValueType    m_amount; unit_base<ValueType> * m_unit;};

    #define QUANTITY Quantity<ValueType,Validator,Traits>template<typename ValueType,typename Validator,typename Traits>QUANTITY inline _cdecl operator+(const QUANTITY & a,           const QUANTITY & b){return (QUANTITY(a)+=b);}

    template<typename ValueType,typename Validator,typename Traits>QUANTITY inline _cdecl operator-(const QUANTITY & a, const QUANTITY & b){return (QUANTITY(a)-=b);}

    #endif /* _QUANTITY_H_ */

    重量:#ifndef _WEIGHT_H_#define _WEIGHT_H_

    #include "../Quantity.h"

    class WeightValidator {};typedef Quantity<double, WeightValidator> Weight;

    /*template<typename ValueType, typename UnitType>Weight inline _cdecl operator*(const ValueType& value, const UnitType& unit ){return Weight(value, unit);}*/

    class Kilogram{public: typedef WeightValidator Validator; static double to_standard(double val) {return val;} static double from_standard(double val) {return val;}};

    class Gramme{public: typedef WeightValidator Validator; static double to_standard(double val) {return val/1000.0;} static double from_standard(double val) {return val*1000.0;}};

    Kilogram _kg;Gramme _g;

    #endif /* _WEIGHT_H_ */

    长度:#ifndef _LENGTH_H_#define _LENGTH_H_

    #include "../Quantity.h"

    class LengthValidator {};typedef Quantity<double, LengthValidator> Length;

    /*template<typename ValueType, typename UnitType>Length inline _cdecl operator*(const ValueType& value, const UnitType& unit ){return Length(value, unit);}*/

    class Meter{public: typedef LengthValidator Validator; static double to_standard(double val) {return val;} static double from_standard(double val) {return val;}};

    class Kilometer{public: typedef LengthValidator Validator; static double to_standard(double val) {return val*1000.0;} static double from_standard(double val) {return val/1000.0;}};

    Meter _m;Kilometer _km;

    #endif /* _LENGTH_H_ */

    测试代码:// Quantity.cpp : Defines the entry point for the console application.//

    #include "stdafx.h"#include "weight.h"#include "length.h"

    void testWeight(){ Weight w1(1.0, _kg); //构造函数 Weight w2(1.0, _g); //构造函数

     Weight w3 = w1; //拷贝构造函数 w3 = w2;  //赋值操作

     Weight w4(1.0, _kg); w4 += w1;  //相同单位相加 w4 += w2;  //不同单位相加 Weight w5 = w4 + w1;  //相同单位相加 w5 = w4 + w2;  //不同单位相加

     Weight w6(2.0, _kg); w6 -= w1;  //相同单位相减 w6 -= w2;  //不同单位相减 Weight w7 = w5 - w1;  //相同单位相减 w7 = w5 - w2;  //不同单位相减

     // 比较 Weight a(1.0, _kg); Weight b(2.0, _kg); Weight c(2000.0, _g); Weight d(3000.0, _g); bool f = (a < b); f = (a < c); f = (b==c); f = (b < d);

     //单位换算 Weight w10(1.0, _kg); w10.convert(_g); w10.convert(_kg);}

    void testLength(){ Length l1(1.0, _km); //构造函数 Length l2(1.0, _m); //构造函数

     Length l3 = l1; //拷贝构造函数 l3 = l2;  //赋值操作

     Length l4(1.0, _km); l4 += l1;  //相同单位相加 l4 += l2;  //不同单位相加 Length l5 = l4 + l1;  //相同单位相加 l5 = l4 + l2;  //不同单位相加

     Length l6(2.0, _km); l6 -= l1;  //相同单位相减 l6 -= l2;  //不同单位相减 Length l7 = l5 - l1;  //相同单位相减 l7 = l5 - l2;  //不同单位相减

     // 比较 Length a(1.0, _km); Length b(2.0, _km); Length c(2000.0, _m); Length d(3000.0, _m); bool f = (a < b); f = (a < c); f = (b==c); f = (b < d);

     //单位换算 Length l10(1.0, _km); l10.convert(_m); l10.convert(_km);}

    void testError(){#if(0) Weight w1; // 没有缺省构造函数 Length l1; // 没有缺省构造函数#endif#if(0) Weight w2(1.0, _km); //错误的单位 Length l2(1.0, _g);  //错误的单位#endif#if(0) Weight w3(1.0, _kg); Length l3(1.0, _m); w3.convert(_km); //错误的单位 l3.convert(_g);  //错误的单位#endif#if(0) Weight w4(1.0, _kg); Length l4(1.0, _m); w4 += l4; //错误的类型 w4 -= l4; //错误的类型#endif#if(0) Weight w5(1.0, _kg); Length l5(1.0, _m); bool f = (w5 == l5); f = (w5 > l5); f = (w5 < l5);#endif}

    int main(int argc, char* argv[]){ testWeight(); testLength(); testError(); return 0;}


    最新回复(0)