简单的数值 variant

原创 2004年07月19日 20:44:00

可改变真实类型的 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;
int
main ()
{
  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;
}

如何从VC的对象_variant_t中获取数值型数据

由于软件中操作的数据是来自数据库的,所以不可避免的就要从数据库中取出相应的数据,用了ADO,随其自然就用了如下的方法来取数据_variant_t tempID;tempID = _rst->GetCo...
  • hekejun19861107
  • hekejun19861107
  • 2010-05-10 14:08:00
  • 3316

Variant 用法详解

Variant 用法详解在你的程序中使用 variant,要包含头文件 "boost/variant.hpp"。这个头文件包含了整个库,所以你不必知道要使用哪些单独的特性;以后,如果你要降低相关性,可...
  • tuwen
  • tuwen
  • 2008-03-24 18:39:00
  • 5146

_variant_t和_bstr_t有什么区别

_variant_t是一个类,它封装了VARIANT类型,而VARIANT是一个万能类型,可以存放任意类型的数据(字符型、日期型、数值型等等); _bstr_t也是一个类,它封装了BSTR类型,BS...
  • liujiayu2
  • liujiayu2
  • 2015-04-07 22:30:42
  • 759

CString 转换成VARIANT类型

CString strVar VARIANT varValue; varValue.vt=VT_BSTR; varValue.bstrVal=(_bstr_t)Var; m_ctlSpread...
  • xuqiang918
  • xuqiang918
  • 2014-05-12 12:18:24
  • 1390

在COM方法中用VARIANT类型传递数组数据

在COM方法中可用VARIANT类型传递数组数据,在VC++中用SAFEARRAY处理。下面给出输入和输出数组的例子     1。输入数组到COM中     STDMETHODIMP     CTes...
  • wzsy
  • wzsy
  • 2008-03-18 10:15:00
  • 1015

样将_variant_转化为vc中的数组

VARIANT,变体类型,在VC 中是一个可以容纳很多常用类型的超级类型,所以,如果不知道它的里面到底存了些什么数据,对着它就像对着一个从未见过面的朋友一样,不知该怎么交流.在这种情况下,我们可以通过...
  • xiaoyaofriend
  • xiaoyaofriend
  • 2012-05-23 10:38:27
  • 3308

VARIANT 转换成 CString

用下面的这个函数就可以了.CString CSelectDlg::VariantToCString(VARIANT var){      CString strValue;     _variant_...
  • jia_xiaoxin
  • jia_xiaoxin
  • 2008-08-22 17:35:00
  • 3869

用实例讲解Variant类型在VB、C#、VC中的参数传递

几年前我用VB开发了一个西门子PPI通信控件,由于VB开发的控件是标准的COM组件,所以想当然的认为VC、C#、Delphi等开发语言可以非常容易的使用。   前段时间由于该控件基于微软的MSC...
  • sgzwiz
  • sgzwiz
  • 2012-03-17 12:34:36
  • 6156

VARIANT与CString相互转换

VARIANT 类型经常用来给 COM 对象传递参数,或者接收从 COM 对象返回的值。你也能自己编写返回 VARIANT 类型的方法,函数返回什么类型 依赖可能(并且常常)方法的输入参数(比如,在...
  • primer_programer
  • primer_programer
  • 2007-12-26 14:39:00
  • 5114

C++ VARIANT数据类型操作详解

使用VARIANT来传递参数意味着非强类型语言(例如VBScript)能够调用使用强类型语言(C++)实现的方法。 VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构...
  • qq_28098067
  • qq_28098067
  • 2016-05-05 17:55:47
  • 4212
收藏助手
不良信息举报
您举报文章:简单的数值 variant
举报原因:
原因补充:

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