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

原创 2002年07月23日 09:11:00

以下是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;
}

分析模式-计量的C++实现——回复ch0877

ch0877翻译了一篇名叫《分析模式-计量》的文章(http://www.csdn.net/Develop/article/14/14449.shtm),很不错。我就试着用C++实现了一下。以下是源代...
  • noho
  • noho
  • 2002年07月19日 09:47
  • 762

reactor模式C++实现

copy from github上的一份实现。。。找不到链接了。。。 感觉epoll主要负责fd到event类型的映射,而reactor模式管理fd event类型 eventhandler具体...
  • u011693064
  • u011693064
  • 2017年05月11日 14:28
  • 380

如何用R做计量经济学

CRAN任务视图:计量经济学 线形回归模型(Linear regression models) ž   线形模型可用stats包中lm()函数通过OLS来拟合,该包中也有各种检验方法用来比...
  • s04023083
  • s04023083
  • 2014年10月22日 16:06
  • 6439

C++完美实现Singleton模式

点击打开链接
  • cbdg3757
  • cbdg3757
  • 2013年09月27日 15:41
  • 252

Android 日夜间模式切换:ThemeDemo

效果图: Github 前面: 实现的原理像我微博之前的说的那样. 关于多主题实现的,我这里的做法是继承AppCompatActivity,置换了AppCompat...
  • richie0006
  • richie0006
  • 2016年03月08日 16:26
  • 603

C++完美实现Singleton模式

C++完美实现Singleton模式 Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却也不是件容易的事情。1.         标准的实现class Singleton{...
  • dongfangyu
  • dongfangyu
  • 2009年08月26日 14:29
  • 1078

C++11:完美转发的使用

完美转发(perfect forwarding)问题是指函数模板在向其他函数转发(传递)自身参数(形参)时该如何保留该参数(实参)的左右值属性的问题。也就是说函数模板在向其他函数转发(传递)自身形参时...
  • aqtata
  • aqtata
  • 2014年06月27日 23:55
  • 3927

C++调用外部程序

关于三个SDK函数:WinExec, ShellExecute,CreateProcess的其他注意事项: 【1】定义头文件 必须定义以下两个头文件: #include // 可替换为 w...
  • eof_2011
  • eof_2011
  • 2012年02月23日 07:54
  • 1252

后台调用外部程序的完美实现(使用CreateDesktop建立隐藏桌面)

提供思路,可用C++完整实现 最近在做的一个软件,其中有一部分功能需要调用其它的软件来完成,而那个软件只有可执行文件,根本没有源代码,幸好,我要做的事不难,只需要在我的程序启动后,将那个软件打开...
  • qwq1503
  • qwq1503
  • 2017年08月21日 13:51
  • 195

LL(1)分析法_C++实现

Code by C++#include #include #include /*******************************************/int count=0; ...
  • shaguabufadai
  • shaguabufadai
  • 2017年05月28日 23:41
  • 382
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:分析模式-计量的C++实现——完美版本
举报原因:
原因补充:

(最多只允许输入30个字)