Class Variant, which can change the real type
After I finished the first edition of Class Variant, I would like to continue to complete another different Variant, which is also intended to have a powerful Boost :: Variant. However, after having a little preliminary idea, I found that I can't write, the reason is very simple, no goals.
My first version of Variant (hereinafter just a variant) target is clear: provide a dynamic type that can vary on several basic types (int, double, etc.). Specifically, it is a variable of any Variant, such as VAR, can participate in , -, *, /,%, etc., but as a result, according to the true type of VAR.
such as:
Variant var; variant_int; // Set its real type to int type var = 1.5; // var == 1 var * = 2; // var == 2
Var.set_type; // Set to Double VAR = 1.5; // var == 1.5 var / = 0.5; // var == 3.0
Variant can support types: int, long, float, and double; support for arithmetic operations and comparison of variables with these four types. Unfortunately, Variant cannot operate with the type outside of these types.
First, set type and assignment
In the constructor, Variant_TypeID and Variant (const string "can specify types; Template Valiant (Type Value) can be specified by Type's type. Member function set_typeId () can set the type at any time and get to get_typeId (), you can get the type of Variant_TypeID value.
Operator = can change the value, but does not change the type; assign () assigns and changes the type. Template Set_Value (Type) Takes the source data as a TYPE type variable and does not change the type; the corresponding Template get_Value () can be taken. In these functions, only ASSIGN () is changed.
Second, the arithmetic operation
Supported arithmetic operations are: ,, *, /,%, and corresponding = and other operators. But pay attention to Float and Double don't have% operations. I have not dealt with this runtime error (I don't know how to handle it).
These arithmetic operations are Variant, which is a variant. But for = such an operator, it seems that the left must be Variant.
Third, comparative operation
The comparison operation supports all six computments, but the final implementation is only == and Fourth, type automatic conversion Variant participates in various operations, inevitably encounters this situation such as int and Double operations, then the type is converted. My setting is: int -> long -> Double and float -> Double. Maybe it should be int-> long-> float -> Double, but I have a prejudice to Float, I really want to press it. achieve: I started using a UNION, and the results are not good, so it is used to dynamically allocate memory, and use a void * to point to the storage unit, and Void * is also easy to convert. In Variant, there are two data members, void * _value, and variant_typeid _type, _Value points to real storage, and _Type specifies the true type. NEW_VARIANT (VARIANT_TYPEID TYPE) is used to assign a Type type space, and the return value is the address of the space. Template New_constructor () points Multiple variables that construct a TYPE type. New_variant () just switched with the switch statement New_constructor (). Similar, there is delete_variant () and delete_destructor (), Delete a variable. There is a large number of variant_typeid to real type conversion, as well as the transformation of Variant_TypeID, which is completed by Template struct typeid2type and template struct type2typeid. These two tools will be wrong for int, long, float, and double. Template get_reference () is a reference to get the real variable of Variant, but I think it is very embarrassing, I have to use it internally. I feel that this function is very important, I really want to change the value. This function must not be used wrong (in fact, which one can not be wrong). Template Set_value (Value) can set VARIANT The value is mainly a Switch statement, and selects the right according to the different real type of Variant. Statement: Switch (_Type) {copy variant_int: get_reference () = value; Break; ... } If the real type is int, then the Variant_int branch will be selected when executed, and the result will be correct. However, if it is not int, it is also required that the Variant_int branch must be able to compile, then the INT must have an assignment operator from Type to INT. The promotion is that all VARIANT supports must have the same series of operators or methods, and they must be convertible between them, which is the biggest limit of Variant. For Template Get_Value (), you need to know the type of return value to operate correctly. For arithmetic operations and comparative operations, if the type of operation does not match, it is to be upgraded to a higher type and then calculate. Function update_typeid () is used to calculate the type of increased type, follow the principle of int-> long-> double and float-> Double. Arithmetic operations and comparison operations are implemented with Plus_Variant (Right), Minus_Variant (), Equal_Variant (), LESS_VARIANT (), etc., these functions are required to require this -> _ Type rating is not lower than Right._Type . The overloaded, such as operators, build a temporary VARIANT TEMP with high type levels, and then call Temp.plus_variant (right) to complete the operation. This is the only thing to make the calculation does not lose accuracy to similar to the grammar requirements. For this kind of Variant, it is important to find a real type and correctly implement the operation. My implementation is really brutal, I am sighing Boost :: Variant's wonderful. Source code: // 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; reason, write to // the Free Software Foundation, 59 Temple Place - Suite 330, Boston, // MA 02111-1307, USA. # iFNDef Variant_Cpp # deflude / * Dynamic type of class * / Class Variant; / * Assign one ID * for each support type ENUM VARIANT_TYPEID { // Variant_Notype, Variant_INT, / * INT * / VARIANT_LONG, / * long * / Variant_float, / * float * / Variant_double / * double * / } / * Conversion from type to type ID * / Template Struct TypeID2TYPE; Template Struct Type2TypeId; / * Higher primary type of transformation when you want two types of operations * / Variant_typeid Update_typeid (variant_typeid left); Template <> struct typeid2type {Typedef int value_type; Template <> struct typeid2type {typedef long value_type; Template <> struct typeid2type {typef float value_type; Template <> struct typeid2type {typef 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 Dynamic Type * / Class Variant { Private: Void * _Value; / * Point to allocated variables * / Variant_typeid _type; / * Current type * / Private: / * Take a reference to real variables, the type given by Type, should ensure that the parameters are correct * / Template TypeName TypeID2TYPE :: Value_Type & Get_reference () { TypeDef TypeName TypeID2TYPE :: Value_type value_type; Return * static_cast (_Value); } / * Take usually reference * / Template Const TypeName TypeId2Type :: Value_Type & Get_reference () const { TypeDef TypeName TypeID2TYPE :: Value_type value_type; Return * static_cast (_Value); } / * Assign and construct a variable that determines the type (it is not flexible enough) * / Template Void * New_constructor () { TypeDef TypeName TypeID2TYPE :: Value_type value_type; Return new value_type; } / * Recycling and destructure a variable * / Template Void Delete_Destructor (Void * PTR) { TypeDef TypeName TypeID2TYPE :: Value_type value_type; Delete static_cast (PTR); } / * Initialize a new variable according to the type ID, return the address of the variable * / 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; } } / * Delete a variable, type ID is 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 st :: string & var_type); Template Variant (Type Value); ~ Variant (); Variant (const variant&); / * Assignment, but does not change the type * / Variant & Operator = (const variant & var); Template Variant & Operator = (Type Value); / * Change type and assign value * / Variant & Assign (Const Variant & Var); Template Variant & Assign (Type T); / * Change the type specified by TYPE * / Variant & Set_typeid (variant_typeid type); / * Get the current type * / Variant_typeid GET_TYPEID () Const; / * Clear the current variable, not * / / * void Clear (); * / / * Take the value of the variable and convert it to type specified by 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; } } / * Give T value * / Template Void Get_Value (Type & T) Const { Const variant_typeid type_id = type2typeid :: Type_id; T = Get_Value (); } / * Set the value of the variable * / 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: / * The following functions, from the addition, subtraction, until it is equal to, less than the comparison, is assumed * THIS Type levels above Right's type * / / * Addition operation, * 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; } } / * Subtilion operation, * 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; } } / * Multiplication, * 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 (); Case variant_float: GET_REFERENCE () * = Right.get_Value (); Break; Case variant_double: GET_REFERENCE () * = Right.get_Value (); Break; } } / * Division operation, * 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; } } / * Search operation, * 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; / * Do not ask for the floating point number, how to deal with? Throw an exception? * / / * Case variant_float: GET_REFERENCE ()% = Right.get_Value (); Break; Case variant_double: GET_REFERENCE ()% = Right.get_Value (); Break; * / } } / * Is equal to comparison, * 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; } } / * Small than the comparison, * this Bool Less_variant (const variant & right) { Switch (_Type) { Case Variant_INT: Return (Get_Reference () ()) Break; Case Variant_long: Return (Get_Reference () ()) Break; Case variant_float: Return (Get_Reference () ()) Break; Case variant_double: Return (Get_Reference () ()) Break; } } PUBLIC: / * The following is? = Type of calculation * / 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; } / * The following is - * /% five calculations * / 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 & 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); / * Comparison operation * / Template Friend Bool Operator == (Const Variant & Left, Type Right); Template Friend Bool Operator == (Type Left, Const Variant & Right); Friend Bool Operator == (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 RIGH); 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 st :: 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&) { 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 (RIGH); 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 (RIGH); 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) { 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) { RTURN RIGHT } Template BOOL Operator> (Type Left, Const Variant & Right) { RTURN RIGHT } Bool Operator> (Const Variant & LEFT, CONST VARIANT & Right) { RTURN RIGHT } / * <= <= <= <= <= <= <= <= <= <= * / Template Bool Operator <= (Const Variant & Left, TYPE RIGHT) { Right } Template Bool Operator <= (Type Left, Const Variant & Right) { Right } Bool Operator <= (Const Variant & LEFT, Const Variant & Right) { Right } / *> => => => => => => => => = * / Template Bool Operator> = (Const Variant & Left, TYPE RIGHT) { Return! (Left } Template BOOL Operator> = (Type Left, Const Variant & Right) { Return! (Left } Bool Operator> = (Const Variant & LEFT, Const Variant & Right) { Return! (Left } #ENDIF Test code: #include "variant.cpp" #include INTMAIN () {variant var (variant_int); variant left; variant right (variant_double); Var.set_Value Right / = left * var; cout << Right.get_Value For (int i = 10; I> 0; I -) {var - = i; Right / = i;} Cout << var.get_value LEFT = 1.0; var = 2.0; Right = Left * Left - 2 * Left * var var * var; cout << Right.get_Value DO {left = 10; var = 10; for (int i = 4; i> 0; I -) {var / = i; left / = i;} cout << var.get_value IF (left.get_typeid () == variant_double) {left.set_typeid (variant_int); variant_typeid;} 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)) cout << "Right" << endl; else cout << "error" << endl; system ("pause"); return 0;}