可改变真实类型的 class variant

  在我完成了 class variant 的第一版后,我想继续完成另一种不同的
variant,这也是看了强大的 boost::variant 后的打算。然而在有了一点点的
初步的想法后,发现我写不下去了,原因很简单,没的目标了。

  我的第一版的 variant(以下只说 variant)目标很明确:提供一种可以变
化在基本的几种数值类型(int、double 等)上的动态类型。具体说,就是任一
个 variant 的变量如 var,都可以参加 +、-、*、/、% 等运算,但其结果,则
依 var 的真实类型而不同。

  比如:

variant var;
  var.set_type (variant_int);   // 设置其真实类型为 int 类型
  var = 1.5;   // var == 1
  var *= 2;    // var == 2

var.set_type (variant_double);  // 设为 double 型
  var = 1.5;   // var == 1.5
  var /= 0.5;  // var == 3.0

  variant 可以支持的类型有:int、long、float 和 double;支持与这四种
类型的变量的进行算术运算和比较运算。很不幸,variant 不能与这四种类型之
外的类型进行运算。

  一、设定类型和赋值

  在构造函数里,variant(variant_typeid) 和 variant(const string&) 可
以指定类型;而 template variant(type value) 可以由 type 的类型指定。成
员函数 set_typeid() 可以随时设定类型,用 get_typeid() 则可以得到类型的
variant_typeid 值。

  operator = 可以改变值,但不改变类型;assign() 赋值并改变类型。
template set_value(type) 把源数据当成 type 型变量再赋值,不改变类型;
相应有 template get_value() 可以取值。这些函数里,只有 assign() 是改变
类型的。

  二、算术运算

  支持的算术运算有:+、-、*、/、%,以及相应的 += 等运算符。但是注意
float 和 double 并没有 % 运算,对这个运行时错误我并没有处理(我不知道
怎样处理好)。

  这些算术运算,对需有一则是 variant 即可。但对于 += 这样的运算符,
似乎左边必须是 variant。

  三、比较运算

  比较运算支持所有的六种运算,但最终的实现是只有 == 和 < 两种,剩下
四种都可以由这两种变化而来。

  四、类型自动转换

  variant 参加各种运算,必然会遇到如 int 与 double 运算的这种情况,
这时就要类型转换了。我的设定是:int -> long -> double 和 float ->
double。可能更应该是 int -> long -> float -> double,但我对 float 实在
是有偏见,实在要打压它。

  实现:

  最开始我是用一个 union 去实现的,结果发现并不好,于是变用动态分配
内存的办法,用一个 void* 指向存储单元,而 void* 也便于转换。在 variant
里,有两个数据成员,void* _value 和 variant_typeid _type,_value 指向
真实的存储空间,而 _type 则指定了真实的类型。

  new_variant(variant_typeid type) 用来分配一个 type 类型的空间,返
回值就是空间的地址。template new_constructor() 分
配并构造一个 type 类型的变量。new_variant() 只是用 switch 语句转而调用
new_constructor()。相似的,有 delete_variant() 和 delete_destructor(),
删除一个变量。

  这里存在有大量的 variant_typeid 到真实类型的转换,还有真实类型到
variant_typeid 的转换,这两项工作分别由 template struct typeid2type 和
template struct type2typeid 完成。对于 int、long、float 和 double 之外
的类型,这两个工具均会报错。

  template get_reference() 是用来取得 variant 真实变量的引用的,可是
我觉得它的身份很尴尬,只好在内部使用。觉得这个函数是很重要的,真正要改
变值都要靠这个。这这个函数绝不能用错了(其实哪一个都不能错啊)。

  template set_value(value) 可以设置 variant
的值,主要是一个 switch 语句,根据 variant 真实类型的不一样而选择合适
的语句:

switch (_type)
  {
  case variant_int:
    get_reference () = value;
    break;
  ...
  }

  如果真实类型是 int,那么执行时会选择 variant_int 支路,结果会是正
确的。但是,如果不是 int,也要求 variant_int 支路必须可以编译通过,则
要求 int 必须有从 type 到 int 的赋值运算符。推广开来就是,所有 variant
支持的类型,必须有相同的一系列运算符或方法,而且它们之间必须是可想互转
换的,这是 variant 最大的限制。

  对于 template get_value() 来说,需要知道返回值的类型,以正确运作。

  对于有算术运算和比较运算来说,如果运算的类型不匹配的话,则要提升到
一个较高的类型,然后再进行去算。函数 update_typeid() 就是用来计算提升
后的类型的,按照 int->long->double 和 float->double 的原则。

  算术运算和比较运算,是借助 plus_variant(right)、minus_variant()、
equal_variant()、less_variant() 等这些函数实现的,这些函数都有一个特点
就是,要求 this->_type 等级不低于 right._type。重载的那些如 + 运算符,
都是先建立一个类型等级高的临时 variant temp,然后再调用
temp.plus_variant (right) 来完成运算。这样做唯一的是为了让运算不丢失精
度,以与语法要求相似。

  对于这种 variant 来说,重要的是找准真实类型并正确实施运算。我的实
现实在是使蛮力,感叹 boost::variant 的精彩。

源代码:

// number variant implementation
// Copyright (C) 2004, BenBear
//
// This file is a class of number variant. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation; either version 2, or (at your option) any later
// version.
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
// MA 02111-1307, USA.
#ifndef variant_cpp
#define variant_cpp
#include
/* 动态类型的类 */
class variant;
/* 为每一种支持的类型分配一个 id */
enum variant_typeid
  {
    //variant_notype,
    variant_int,     /* int 型 */
    variant_long,    /* long 型 */
    variant_float,   /* float 型 */
    variant_double   /* double 型 */
  };
/* 从类型到类型 id 的转换 */
template struct typeid2type;
template struct type2typeid;
/* 求两种类型运算时要转化的更高一级类型 */
variant_typeid
update_typeid (variant_typeid left, variant_typeid right);
template <> struct typeid2type
{ typedef int value_type; };
template <> struct typeid2type
{ typedef long value_type; };
template <> struct typeid2type
{ typedef float value_type; };
template <> struct typeid2type
{ typedef double value_type; };
template <> struct type2typeid
{ static const variant_typeid type_id = variant_int; };
template <> struct type2typeid
{ static const variant_typeid type_id = variant_long; };
template <> struct type2typeid
{ static const variant_typeid type_id = variant_float; };
template <> struct type2typeid
{ static const variant_typeid type_id = variant_double; };
/* variant 动态类型 */
class variant
{
private:
  void* _value;          /* 指向分配的变量 */
  variant_typeid _type;  /* 当前的类型 */
private:
  /* 取得真实变量的引用,类型由 type 给出,应该保证参数是正确的 */
  template
  typename typeid2type ::value_type&
  get_reference ()
  {
    typedef typename typeid2type ::value_type value_type;
    return *static_cast (_value);
  }
 
  /* 取常引用 */
  template
  const typename typeid2type ::value_type &
  get_reference () const
  {
    typedef typename typeid2type ::value_type value_type;
    return *static_cast (_value);
  }
 
  /* 分配并构造一个确定类型的变量(好象不够灵活) */
  template
  void*
  new_constructor ()
  {
    typedef typename typeid2type ::value_type value_type;
    return new value_type;
  }
  /* 回收并析构一个变量 */
  template
  void
  delete_destructor (void* ptr)
  {
    typedef typename typeid2type ::value_type value_type;
    delete static_cast (ptr);
  }
  /* 根据类型 id 初始化一个新的变量,返回变量的地址 */
  void*
  new_variant (variant_typeid type)
  {
    switch (type)
      {
      case variant_int:
return new_constructor ();
break;
      case variant_long:
return new_constructor ();
break;
      case variant_float:
return new_constructor ();
break;
       case variant_double:
return new_constructor ();
break;
     }
  }
  /* 删除一个变量,类型 id 为 type */
  void
  delete_variant (variant_typeid type, void* ptr)
  {
    switch (type)
      {
      case variant_int:
delete_destructor (ptr);
break;
      case variant_long:
delete_destructor (ptr);
break;
      case variant_float:
delete_destructor (ptr);
break;
      case variant_double:
delete_destructor (ptr);
break;
      }
  }
public:
  explicit variant (variant_typeid var_type = variant_int);
  explicit variant (const std::string& var_type);
  template
  variant (type value);
  ~variant ();
  variant (const variant& var);
  /* 赋值,但不改变类型 */
  variant& operator = (const variant& var);
  template
  variant& operator = (type value);
  /* 改变类型并赋值 */
  variant&
  assign (const variant& var);
  template
  variant&
  assign (type t);
  /* 改变类型为 type 所指定的类型 */
  variant&
  set_typeid (variant_typeid type);
  /* 取得当前的类型 */
  variant_typeid
  get_typeid () const;
  /* 把当前变量清空,暂不用 */
  /*void
    clear ();*/
  /* 取变量的值,并转换成 type 指定的类型 */
  template
  typename typeid2type ::value_type
  get_value () const
  {
    typedef typename typeid2type ::value_type value_type;
    switch (_type)
      {
      case variant_int:
return static_cast (get_reference ());
break;
      case variant_long:
return static_cast (get_reference ());
break;
      case variant_float:
return static_cast (get_reference ());
break;
      case variant_double:
return static_cast (get_reference ());
break;
      }
  }
  /* 给 t 赋值 */
  template
  void
  get_value (type& t) const
  {
    const variant_typeid type_id = type2typeid ::type_id;
    t = get_value ();
  }
  /* 设定变量的值 */
  template
  void
  set_value (typename typeid2type ::value_type value)
  {
    typedef typename typeid2type ::value_type value_type;
    typedef typeid2type ::value_type int_type;
    typedef typeid2type ::value_type long_type;
    typedef typeid2type ::value_type float_type;
    typedef typeid2type ::value_type double_type;
    switch (_type)
      {
      case variant_int:
get_reference () = static_cast (value);
break;
      case variant_long:
get_reference () = static_cast (value);
break;
      case variant_float:
get_reference () = static_cast (value);
break;
      case variant_double:
get_reference () = static_cast (value);
break;
      }
  }
 
private:
  /* 以下几个函数,从加法、减法一直到等于、小于比较,都是假定 *this 的
     类型等级要高于 right 的类型 */
  /* 加法运算,*this += right */
  void
  plus_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
get_reference () += right.get_value ();
break;
      case variant_long:
get_reference () += right.get_value ();
break;
      case variant_float:
get_reference () += right.get_value ();
break;
      case variant_double:
get_reference () += right.get_value ();
break;
      }
  }
  /* 减法运算,*this -= right */
  void
  minus_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
get_reference () -= right.get_value ();
break;
      case variant_long:
get_reference () -= right.get_value ();
break;
      case variant_float:
get_reference () -= right.get_value ();
break;
      case variant_double:
get_reference () -= right.get_value ();
break;
      }
  }
  /* 乘法运算,*this *= right */
  void
  multi_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
get_reference () *= right.get_value ();
break;
      case variant_long:
get_reference () *= right.get_value ();
break;
      case variant_float:
get_reference () *= right.get_value ();
break;
      case variant_double:
get_reference () *= right.get_value ();
break;
      }
  }
  /* 除法运算,*this /= right */
  void
  div_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
get_reference () /= right.get_value ();
break;
      case variant_long:
get_reference () /= right.get_value ();
break;
      case variant_float:
get_reference () /= right.get_value ();
break;
      case variant_double:
get_reference () /= right.get_value ();
break;
      }
  }
  /* 求余运算,*this %= right */
  void
  mod_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
get_reference () %= right.get_value ();
break;
      case variant_long:
get_reference () %= right.get_value ();
break;
/* 对浮点数没有求余运算,怎么处理?抛出异常? */
/*
case variant_float:
   get_reference () %= right.get_value ();
   break;
case variant_double:
   get_reference () %= right.get_value ();
   break;
*/
      }
  }
  /* 等于比较,*this == right */
  bool
  equal_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
return (get_reference ()
  == right.get_value ());
break;
      case variant_long:
return (get_reference ()
  == right.get_value ());
break;
      case variant_float:
return (get_reference ()
  == right.get_value ());
break;
      case variant_double:
return (get_reference ()
  == right.get_value ());
break;
      }
  }
  /* 小于比较,*this < right */
  bool
  less_variant (const variant& right)
  {
    switch (_type)
      {
      case variant_int:
return (get_reference ()
  < right.get_value ());
break;
      case variant_long:
return (get_reference ()
  < right.get_value ());
break;
      case variant_float:
return (get_reference ()
  < right.get_value ());
break;
      case variant_double:
return (get_reference ()
  < right.get_value ());
break;
      }
  }
public:
  /* 以下为 ?= 类型的运算 */
  template
  variant& operator += (type right)
  {
    const variant_typeid right_typeid = type2typeid ::type_id;
    variant_typeid pub_typeid = update_typeid (_type, right_typeid);
    variant temp(pub_typeid);
    temp.template set_value (right);
    temp.plus_variant (*this);
    *this = temp;
    return *this;
  }
  template
  variant& operator -= (type right)
  {
    const variant_typeid right_typeid = type2typeid ::type_id;
    variant_typeid pub_typeid = update_typeid (_type, right_typeid);
    variant temp_right(right_typeid);
    temp_right.template set_value (right);
    variant temp(pub_typeid);
    temp = *this;
    temp.minus_variant (temp_right);
    *this = temp;
    return *this;
  }
  template
  variant& operator *= (type right)
  {
    const variant_typeid right_typeid = type2typeid ::type_id;
    variant_typeid pub_typeid = update_typeid (_type, right_typeid);
    variant temp(pub_typeid);
    temp.template set_value (right);
    temp.multi_variant (*this);
    *this = temp;
    return *this;
  }
  template
  variant& operator /= (type right)
  {
    const variant_typeid right_typeid = type2typeid ::type_id;
    variant_typeid pub_typeid = update_typeid (_type, right_typeid);
    variant temp_right(pub_typeid);
    temp_right.template set_value (right);
    variant temp(pub_typeid);
    temp = *this;
    temp.div_variant (temp_right);
    *this = temp;
    return *this;
  }
  template
  variant& operator %= (type right)
  {
    const variant_typeid right_typeid = type2typeid ::type_id;
    variant_typeid pub_typeid = update_typeid (_type, right_typeid);
    variant temp_right(pub_typeid);
    temp_right.template set_value (right);
    variant temp(pub_typeid);
    temp = *this;
    temp.mod_variant (temp_right);
    *this = temp;
    return *this;
  }
  variant& operator += (const variant& var)
  {
    variant_typeid pub_typeid = update_typeid (_type, var._type);
    variant temp(pub_typeid);
    temp = *this;
    temp.plus_variant (var);
    *this = temp;
    return *this;
  }
  variant& operator -= (const variant& var)
  {
    variant_typeid pub_typeid = update_typeid (_type, var._type);
    variant temp(pub_typeid);
    temp = *this;
    temp.minus_variant (var);
    *this = temp;
    return *this;
  }
  variant& operator *= (const variant& var)
  {
    variant_typeid pub_typeid = update_typeid (_type, var._type);
    variant temp(pub_typeid);
    temp = *this;
    temp.multi_variant (var);
    *this = temp;
    return *this;
  }
  variant& operator /= (const variant& var)
  {
    variant_typeid pub_typeid = update_typeid (_type, var._type);
    variant temp(pub_typeid);
    temp = *this;
    temp.div_variant (var);
    *this = temp;
    return *this;
  }
  variant& operator %= (const variant& var)
  {
    variant_typeid pub_typeid = update_typeid (_type, var._type);
    variant temp(pub_typeid);
    temp = *this;
    temp.mod_variant (var);
    *this = temp;
    return *this;
  }
  /* 以下是 + - * / % 五种运算 */
  template friend
  variant operator + (const variant& left, type right);
  template friend
  variant operator + (type left, const variant& right);
  friend
  variant operator + (const variant& left, const variant& right);
  template friend
  variant operator - (const variant& left, type right);
  template friend
  variant operator - (type left, const variant& right);
  friend
  variant operator - (const variant& left, const variant& right);
  template friend
  variant operator * (const variant& left, type right);
  template friend
  variant operator * (type left, const variant& right);
  friend
  variant operator * (const variant& left, const variant& right);
  template friend
  variant operator / (const variant& left, type right);
  template friend
  variant operator / (type left, const variant& right);
  friend
  variant operator / (const variant& left, const variant& right);
  template friend
  variant operator % (const variant& left, type right);
  template friend
  variant operator % (type left, const variant& right);
  friend
  variant operator % (const variant& left, const variant& right);
  /* 比较运算 */
  template friend
  bool operator == (const variant& left, type right);
  template friend
  bool operator == (type left, const variant& right);
  friend
  bool operator == (const variant& left, const variant& right);
  template friend
  bool operator != (const variant& left, type right);
  template friend
  bool operator != (type left, const variant& right);
  friend
  bool operator != (const variant& left, const variant& right);
  template friend
  bool operator < (const variant& left, type right);
  template friend
  bool operator < (type left, const variant& right);
  friend
  bool operator < (const variant& left, const variant& right);
  template friend
  bool operator > (const variant& left, type right);
  template friend
  bool operator > (type left, const variant& right);
  friend
  bool operator > (const variant& left, const variant& right);
  template friend
  bool operator <= (const variant& left, type right);
  template friend
  bool operator <= (type left, const variant& right);
  friend
  bool operator <= (const variant& left, const variant& right);
  template friend
  bool operator >= (const variant& left, type right);
  template friend
  bool operator >= (type left, const variant& right);
  friend
  bool operator >= (const variant& left, const variant& right);
};

variant_typeid
update_typeid (variant_typeid left, variant_typeid right)
{
  if ((left == variant_double) || (right == variant_double))
    return variant_double;
  if ((left == variant_float) && (right == variant_float))
    return variant_float;
  if ((left == variant_float) || (right == variant_float))
    return variant_double;
  if ((left == variant_long) || (right == variant_long))
    return variant_long;
  return variant_int;
}
variant::variant (variant_typeid var_type)
{
  _type = var_type;
  _value = new_variant (_type);
}
variant::variant (const std::string& var_type)
{
  if (var_type == "int")
    _type = variant_int;
  else if (var_type == "long")
    _type = variant_long;
  else if (var_type == "float")
    _type = variant_float;
  else if (var_type == "double")
    _type = variant_double;
  _value = new_variant (_type);
}
template
variant::variant (type value)
{
  const variant_typeid type_id = type2typeid ::type_id;
  _type = type_id;
  _value = new_variant (_type);
 
  get_reference () = value;
}
variant::~variant ()
{
  if (_value != 0)
    delete_variant (_type, _value);
}
variant::variant (const variant& var)
{
  _type = var._type;
  _value = new_variant (_type);
  *this = var;
}
variant&
variant::operator = (const variant& var)
{
  switch (_type)
    {
    case variant_int:
      get_reference () = var.get_value ();
      break;
    case variant_long:
      get_reference () = var.get_value ();
      break;
    case variant_float:
      get_reference () = var.get_value ();
      break;
    case variant_double:
      get_reference () = var.get_value ();
      break;
    }
  return *this;
}
template
variant&
variant::operator = (type t)
{
  set_value ::type_id>(t);
  return *this;
}
variant&
variant::assign (const variant& var)
{
  delete_variant (_type, _value);
 
  _type = var._type;
  _value = new_variant (_type);
  *this = var;
  return *this;
}
template
variant&
variant::assign (type value)
{
  if (_value != 0)
    delete_variant (_type, _value);
  const variant_typeid type_id = type2typeid ::type_id;
  _type = type_id;
  _value = new_variant (_type);
  get_reference () = value;
}
/*
void
variant::clear ()
{
  if (_value != 0)
    {
      delete_variant (_type, _value);
     
      _type = variant_notype;
      _value = 0;
    }
}
*/
variant&
variant::set_typeid (variant_typeid type)
{
  //clear ();
  if (_value != 0)
    delete_variant (_type, _value);
 
  _type = type;
  _value = new_variant (_type);
}
variant_typeid
variant::get_typeid () const
{
  return _type;
}
/* +++++++++++++++++++++++++++++++++++++++++++ */
template
variant
operator + (const variant& left, type right)
{
  variant_typeid left_typeid = left._type;
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp (pub_typeid);
  temp.template set_value (right);
  temp.plus_variant (left);
  return temp;
}
template
variant
operator + (type left, const variant& right)
{
  return right + left;
}
variant
operator + (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
  variant temp(pub_typeid);
  temp = left;
  temp.plus_variant (right);
  return temp;
}
/*  -------------------------------------------  */
template
variant
operator - (const variant& left, type right)
{
  variant_typeid left_typeid = left._type;
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp_right (pub_typeid);
  temp_right.template set_value (right);
  variant temp (pub_typeid);
  temp = left;
  temp.minus_variant (temp_right);
  return temp;
}
template
variant
operator - (type left, const variant& right)
{
  variant_typeid right_typeid = right._type;
  const variant_typeid left_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp (pub_typeid);
  temp = left;
  temp.minus_variant (right);
  return temp;
}
variant
operator - (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
  variant temp(pub_typeid);
  temp = left;
  temp.minus_variant (right);
  return temp;
}
/*  *************************************  */
template
variant
operator * (const variant& left, type right)
{
  variant_typeid left_typeid = left._type;
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp (pub_typeid);
  temp.template set_value (right);
  temp.multi_variant (left);
  return temp;
}
template
variant
operator * (type left, const variant& right)
{
  return right * left;
}
variant
operator * (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
  variant temp(pub_typeid);
  temp = left;
  temp.multi_variant (right);
  return temp;
}
/*    */
template
variant
operator / (const variant& left, type right)
{
  variant_typeid left_typeid = left._type;
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp_right (pub_typeid);
  temp_right.template set_value (right);
  variant temp (pub_typeid);
  temp = left;
  temp.div_variant (temp_right);
  return temp;
}
template
variant
operator / (type left, const variant& right)
{
  variant_typeid right_typeid = right._type;
  const variant_typeid left_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp (pub_typeid);
  temp = left;
  temp.div_variant (right);
  return temp;
}
variant
operator / (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
  variant temp(pub_typeid);
  temp = left;
  temp.div_variant (right);
  return temp;
}
/*  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  */
template
variant
operator % (const variant& left, type right)
{
  variant_typeid left_typeid = left._type;
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp_right (pub_typeid);
  temp_right.template set_value (right);
  variant temp (pub_typeid);
  temp = left;
  temp.mod_variant (temp_right);
  return temp;
}
template
variant
operator % (type left, const variant& right)
{
  variant_typeid right_typeid = right._type;
  const variant_typeid left_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right_typeid);
 
  variant temp (pub_typeid);
  temp = left;
  temp.mod_variant (right);
  return temp;
}
variant
operator % (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
  variant temp(pub_typeid);
  temp = left;
  temp.mod_variant (right);
  return temp;
}
/*  == == == == == == == == == ==  */
template
bool operator == (const variant& left, type right)
{
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left._type, right_typeid);
  variant temp(pub_typeid);
  temp = right;
  return temp.equal_variant (left);
}
template
bool operator == (type left, const variant& right)
{
  return right == left;
}
bool operator == (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
 
  variant temp(pub_typeid);
  temp = left;
  return temp.equal_variant (right);
}
/*  != != != != != != != !=  */
template
bool operator != (const variant& left, type right)
{
  return !(left == right);
}
template
bool operator != (type left, const variant& right)
{
  return !(right == left);
}
bool operator != (const variant& left, const variant& right)
{
  return !(left == right);
}
/*  <  <  <  <  <  <  <  <  <   */
template
bool operator < (const variant& left, type right)
{
  const variant_typeid right_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left._type, right_typeid);
  variant temp_right(pub_typeid);
  temp_right = right;
  variant temp(pub_typeid);
  temp = left;
  return temp.less_variant (temp_right);
}
template
bool operator < (type left, const variant& right)
{
  const variant_typeid left_typeid = type2typeid ::type_id;
  variant_typeid pub_typeid = update_typeid (left_typeid, right._type);
  variant temp(pub_typeid);
  temp = left;
  return temp.less_variant (right);
}
bool operator < (const variant& left, const variant& right)
{
  variant_typeid pub_typeid = update_typeid (left._type, right._type);
 
  variant temp(pub_typeid);
  temp = left;
  return temp.less_variant (right);
}
/*  >  >  >  >  >  >  >  >   */
template
bool operator > (const variant& left, type right)
{
  return right < left;
}
template
bool operator > (type left, const variant& right)
{
  return right < left;
}
bool operator > (const variant& left, const variant& right)
{
  return right < left;
}
/*  <= <= <= <= <= <= <= <= <= <=  */
template
bool operator <= (const variant& left, type right)
{
  return !(right < left);
}
template
bool operator <= (type left, const variant& right)
{
  return !(right < left);
}
bool operator <= (const variant& left, const variant& right)
{
  return !(right < left);
}
/*  >= >= >= >= >= >= >= >= >=  */
template
bool operator >= (const variant& left, type right)
{
  return !(left < right);
}
template
bool operator >= (type left, const variant& right)
{
  return !(left < right);
}
bool operator >= (const variant& left, const variant& right)
{
  return !(left < right);
}
#endif

测试代码:

#include "variant.cpp"
#include <iostream>#include <cstdlib>using namespace std;
intmain (){  variant var(variant_int);  variant left(variant_double);  variant right(variant_double);
  var.set_value<variant_double>(300.0);  cout << var.get_value<variant_int>() << endl;

  left = 0.0;  right = 1;  for (int i = 1; i < 10; i++)    {      left += i;      right *= i;    }
  cout << left.get_value<variant_double>() << endl;  cout << right.get_value<variant_double>() << endl;
  right /= left * var;  cout << right.get_value<variant_double>() << endl;
  for (int i = 10; i > 0; i--)    {      var -= i;      right /= i;    }
  cout << var.get_value<variant_int>() << endl;  cout << right.get_value<variant_double>() << endl;
  left = 1.0;  var = 2.0;  right = left * left - 2 * left * var + var * var;  cout << right.get_value<variant_double>() << endl;
  do    {      left = 10;      var = 10; for (int i = 4; i > 0; i--)   {     var /= i;     left /= i;   }      cout << var.get_value<variant_double>() << endl;      cout << left.get_value<variant_double>() << endl;
      if (left.get_typeid () == variant_double) {   left.set_typeid (variant_int);   var.set_typeid (variant_double); }      else if (left.get_typeid () == variant_int) break;    }  while (true);
  var = 0;  left = 0;  right = 0;  for (int i = 1; i <= 10; i++)    {      var += i;      left += var - i;      right += left / var;    }  double d = 0.0;  right.get_value (d);  cout << d << endl;  if (d == right)    cout << "right" << endl;  if (var > d)    cout << "right" << endl;
  var = 1;  if ((var == 1) && (1 == var) && (var < 2) && (2 > var)      && (var <= 1.1) && (1.1 >= var) && (var != 1.1) && (2 != var))    cout << "right" << endl;  else    cout << "error" << endl;  left = 1;  if ((var == left) && (left == var) && (var <= left) && (var >= left))    cout << "right" << endl;  else    cout << "error" << endl;
  system ("Pause");  return 0;}

简单的数值 variant相关推荐

  1. Java 上机题 1.9 Guess 简单猜数值游戏

    题目要求: 1.9 Guess 简单猜数值游戏. 编写⼀个名为Guess的类.在其构造⽅法⽤系统时间对随机数⽣成器种⼦化 以防⽌每次⽣成的随机数序列相同(类java.util.Random):成员⽅法 ...

  2. 计算机科学和Python编程导论(三) 一些简单的数值程序

    基本概念 1. 穷举法 穷举法:是猜测与检验算法的一个变种.我们枚举所有可能性,直至得到正确答案或者尝试完所有值. #寻找完全立方数的立方根 x = int(input('Enter an integ ...

  3. MATLAB当中一些简单的数值分析函数总结

    求解函数的近似根: 二分法相关的MATLAB函数 function [x]=dichotomy(f,a,b,TOL) % f:原函数,a,b:求根区间,需要自定义给出,TOL:误差范围 N=1+fix ...

  4. 中奖人js滚动效果_jQuery实现中奖播报功能(让文本滚动起来) 简单设置数值即可...

    在很多场景中,我们需要使用到中奖信息播报,或者一些文本信息循环滚动播报,在结合实际的开发中,然后也百度查询了相关的知识点,现在送上jQuery实现文本滚动. 1:html代码文件 相关使用说明也在页面 ...

  5. 简单体会数值求解一维扩散方程

    借用这个题目 然后用比较简单的matlab代码来求解 %空间0到1,切了5份,时间0到1,切了十份. clc,clear v = 1; dx = 0.2; x = 0:dx:1; dt = 0.1; ...

  6. VARIANT变体类型数据

    2019独角兽企业重金招聘Python工程师标准>>> 特殊 Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据.Variant ...

  7. Variant 数据类型介绍

    Variant 数据类型是所有没被显式声明(用如 Dim.Private.Public 或 Static等语句)为其他类型变量的数据类型.Variant 数据类型并没有类型声明字符. Variant ...

  8. variant 类型

    Variant 音标 Phonetic symbol [] 词性及解释 Part of speech and defination n. 变体, 异体 a. 不同的, 有差别的 [计] 变体型 [化] ...

  9. C++变体数据类型—— VARIANT

    百度百科: Variant 音标 Phonetic symbol [] 词性及解释 Part of speech and defination n. 变体, 异体 a. 不同的, 有差别的 [计] 变 ...

最新文章

  1. PC端、移动端手机竖拍原图压缩上传顺时针旋转90°的解决方案
  2. 微信人人商城云服务器,微信支付 · 微智人人商城使用文档 · 看云
  3. oligo包处理原始芯片数据
  4. C#委托与事件学习笔记
  5. VS2017 error C3646: 未知重写说明符
  6. 开发每个静态网站是的模版代码(自己开发是长期优化过的觉得最简的代码)
  7. vue项目如何打包扔向服务器 - Hi-Sen - 博客园
  8. 搭建Spring MVC 4开发环境八步走
  9. 两大图灵奖得主点赞中国用AI检测新冠,AI还能做什么?
  10. 进程间通信方式_第四十九期-Linux内核中的进程概述(4)
  11. jquery实现的时间轴
  12. LeetCode刷题(50)--Word Search
  13. hnu 暑期实训之web导航
  14. 是德科技成功开发广泛的测试与测量产品
  15. cmd命令行开启windows远程桌面服务
  16. 深入浅出MySQL数据库开发、优化与管理维护
  17. selenium下载图片
  18. 如何撰写《软件项目方案文档》
  19. 基于Google Edge TPU的Coral USB加速棒体验
  20. EMC Navisphere AGENT(NAVIAGENT) 安装日志

热门文章

  1. 2023年网络安全十10大发展趋势发布
  2. Book——电力系统规划与可靠性
  3. 一周信创舆情观察(9.6~9.12)
  4. 走自己的路,听别人的话
  5. LwIP 用串口当网卡
  6. Ecplise必须知道的配置
  7. JS入门,写一句你自己喜欢的话吧!
  8. golang向上取整、向下取整和四舍五入
  9. 基于Ohta颜色空间的火焰分割
  10. matlab分数写成上下分子形式,word怎么把分数写成上下型的