In many cases, I want to easily express multiple States with one variable. for example, if I have a window class that indicates whether the window has a system menu, a minimum button, a maximum button, or a Help button, four variables may be required to record the window.
Bool hassystemmenu;
Bool hasminimize;
Bool hasmaximize;
Bool hashelp;
In this way, more memory is needed. Although the bit domain can save the memory, the operation is not convenient.
Delphi does a good job of this. Use the set of keyword to declare a set type of data:
Twindowbutton = (hassystemmenu, hasminimize, hasmaximize, hashelp );
Twindowbuttonset = set of twindowbutton;
It is convenient to use and efficient. The code and the corresponding Assembly Code are as follows:
Procedure tform1.button1click (Sender: tobject );
VaR
Button: twindowbuttonset;
Begin
Include (button, hasminimize); or BL, 02
Include (button, hasmaximize); or BL, 04
Exclude (button, hasmaximize); and BL, $ FB
If hasminimize in button then test BL, 02
JZ xxxx
...
End;
Intuitively, it can also be implemented using C ++. The first method I came up with was to declare an enumeration and use the feature that enumeration can be converted to an integer to perform a set operation on the enumeration type. For example:
Enum testenum {T1, T2, T3, T4 };
In this way, set = set | (1 <t1)
Set = set & (0 xffffffff ^ (1 <t2 ))
This is not good enough. The values involved in the set operation are determined during the runtime, while the values of the set type involved in the operation of Delphi are determined during the compilation period. Fortunately, we have a template to realize the compilation period value, definition:
Template <int value>
Class enumvalue
{
Public:
Enum {size = 1 <value };
Enum {nsize = 0 xffffffff ^ (1 <value )};
};
To try cout <enumvalue <t3>: size; output 4
Haha, OK, the rest is code writing. The completed version is as follows, and the efficiency is not lower than that of Delphi. The disadvantage is that it only supports a maximum of 32 Members.
/*
By swordsman smile
Simulate the set data unit of Delphi
*/
# Ifndef p_set_h
# Define p_set_h
// Returns the value of 1 shifted to the right. The template is used to evaluate the value during compilation.
Template <int value>
Class enumvalue
{
Public:
Enum {size = 1 <value };
Enum {nsize = 0 xffffffff ^ (1 <value )};
};
Template <typename T>
Class enumset
{
PRIVATE:
Int _ value;
Public:
Explicit enumset (bool contain)
{
// Whether to include all members during initialization
If (contain)
_ Value = 0 xffffffff;
Else
_ Value = 0;
}
// Contains an enumeration. parameters are transmitted using a template instead of parameters.
// Determine the value during the release period to improve efficiency
Template <t value>
Void include ()
{
_ Value | = enumvalue <value >:: size;
}
// Remove an enumeration
Template <t value>
Void exclude ()
{
_ Value & = enumvalue <value >:: nsize;
}
// Determines whether an enumeration exists.
Template <t value>
Bool has ()
{
Return _ value & enumvalue <value >:: size;
}
// Determine whether the set is empty
Bool empty ()
{
Return _ value = 0;
}
};
# Endif // p_set_h
------------------------------------------- Separation line --------------------------
Test code:
# Include <iostream>
# Include <string>
# Include <math. h>
# Include "pset. H"
Using STD: CIN;
Using STD: cout;
Using STD: Endl;
Enum testenum {hassystemmenu, hasminimize, hasmaximize, hashelp };
Int main ()
{
Enumset <testenum> set (false );
Set. Include Set. Include Set. Exclude
If (set. Has Cout <"hassystemmenu" <Endl;
If (set. Has Cout <"hasminimize" <Endl;
If (set. Has Cout <"hasmaximize" <Endl;
Cin. Get ();
Return 0;
}