简单的数值 variant
可改变真实类型的 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相关推荐
- Java 上机题 1.9 Guess 简单猜数值游戏
题目要求: 1.9 Guess 简单猜数值游戏. 编写⼀个名为Guess的类.在其构造⽅法⽤系统时间对随机数⽣成器种⼦化 以防⽌每次⽣成的随机数序列相同(类java.util.Random):成员⽅法 ...
- 计算机科学和Python编程导论(三) 一些简单的数值程序
基本概念 1. 穷举法 穷举法:是猜测与检验算法的一个变种.我们枚举所有可能性,直至得到正确答案或者尝试完所有值. #寻找完全立方数的立方根 x = int(input('Enter an integ ...
- MATLAB当中一些简单的数值分析函数总结
求解函数的近似根: 二分法相关的MATLAB函数 function [x]=dichotomy(f,a,b,TOL) % f:原函数,a,b:求根区间,需要自定义给出,TOL:误差范围 N=1+fix ...
- 中奖人js滚动效果_jQuery实现中奖播报功能(让文本滚动起来) 简单设置数值即可...
在很多场景中,我们需要使用到中奖信息播报,或者一些文本信息循环滚动播报,在结合实际的开发中,然后也百度查询了相关的知识点,现在送上jQuery实现文本滚动. 1:html代码文件 相关使用说明也在页面 ...
- 简单体会数值求解一维扩散方程
借用这个题目 然后用比较简单的matlab代码来求解 %空间0到1,切了5份,时间0到1,切了十份. clc,clear v = 1; dx = 0.2; x = 0:dx:1; dt = 0.1; ...
- VARIANT变体类型数据
2019独角兽企业重金招聘Python工程师标准>>> 特殊 Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据.Variant ...
- Variant 数据类型介绍
Variant 数据类型是所有没被显式声明(用如 Dim.Private.Public 或 Static等语句)为其他类型变量的数据类型.Variant 数据类型并没有类型声明字符. Variant ...
- variant 类型
Variant 音标 Phonetic symbol [] 词性及解释 Part of speech and defination n. 变体, 异体 a. 不同的, 有差别的 [计] 变体型 [化] ...
- C++变体数据类型—— VARIANT
百度百科: Variant 音标 Phonetic symbol [] 词性及解释 Part of speech and defination n. 变体, 异体 a. 不同的, 有差别的 [计] 变 ...
最新文章
- java使用线程求素数和1000个0~0.9随机数_求素数(多线程练习题)
- ubuntu nano用法
- Kubernetes的ConfigMap说明
- 使用keepalived加lvs做负载均衡,访问后端的服务器,2分钟后超时,需要重新登录...
- 静态库和动态库详解(部分参考别人)
- .net core 微服务之API网关 开源中间件 Ocelot 笔记
- Memory与Merge特性
- java 线程死锁简单例子_java 多线程死锁详解及简单实例
- php 父子id,父子关系PHP / MYSQL
- 51单片机初值计算方法
- win10下安装 迅雷精简版,提示阻止此应用
- 天津联通移动电信DNS
- 平面/球面坐标中已知起点坐标、(偏转)角度、长度求终点坐标(三角函数)
- 最新封装版EVE模拟器部署和使用说明(图文版)
- LVS的NAT、TUNNEL、Full-NAT模式
- html图片右上角删除按钮,图片右上角删除
- rootkit概念摘抄
- Java 设置PDF平铺图片背景(水印)
- 集十三位资深程序员毕生功力回答:普通程序员如何自学才能进大厂?
- python文件生成exe文件
热门文章
- python [::-1] [::-1,::-1]
- 机器学习中的相似性度量
- 科技公司怎么选择安全高效的企业邮箱
- 提高编程思维的python代码
- [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)
- 802.11n 5GHz信道划分图
- Java32位Win7系统Jdk_win7 32位旗舰版配置与调试JDK环境技巧【图文】
- css设置背景为半透明
- python词云库——wordcloud
- Comparable的用法