用C++模拟DELPHI的set数据类型.

本文介绍了一种使用C++模拟DELPHI中集合类型的高效方法,通过模板元编程实现枚举类型的集合操作,支持多达32个成员的状态表示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多时候,我希望能用一个变量方便的表示多种状态.例如我有一个窗口类,要表示此窗口是否具有系统菜单,最小化按钮,最大化按钮,帮助按钮,可能需要四个变量来记录.
bool hasSystemMenu;
bool hasMinimize;
bool hasMaximize;
bool hasHelp;
这样要占用更多的内存.虽然用位域可以节约内存,但操作不方便.
DELPHI这点就做得不错,用set of 关键字声明一个集合类型数据.如下:
  TWindowButton = (hasSystemMenu, hasMinimize, hasMaximize, hasHelp);
  TWindowButtonSet = set of TWindowButton;
使用也很方便,并且高效.代码和对应的汇编代码如下:
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;
很直观,用C++也能实现,我首先想到的办法是声明一个枚举,利用枚举能转换为整型的特性,针对枚举类型进行集合操作.例如
enum TestEnum {T1, T2, T3, T4};

使用时大概这样,  set = set | (1 << T1)
                               set = set & (0xFFFFFFFF ^ (1 << T2))
这不够好,参与set运算的值都是运行期确定的,而DELPHI的set类型参与运算的值是编译期确定的,还好我们有模板,能够实现编译期求值,定义如下:
template<int Value>
class EnumValue
{
public:
    enum { size = 1 << Value };
    enum { nsize = 0xFFFFFFFF ^ (1 << Value) };
};

来试试 cout << EnumValue<T3>::size ;     输出4
呵呵,OK,剩下的就是写代码的工作了.完成版如下,效率不比DELPHI的低,缺点是只支持最大32个成员

/*
  by 剑神一笑
  模拟DELPHI的Set数据单元
*/

#ifndef P_SET_H
#define P_SET_H

//给出1右移Value次的值,使用模板是为了在编译期能求值
template<int Value>
class EnumValue
{
public:
    enum { size = 1 << Value };
    enum { nsize = 0xFFFFFFFF ^ (1 << Value) };
};

template<typename T>
class EnumSet
{
private:
    int _value;
public:
    explicit EnumSet(bool contain)
    {
        //是否初始化时就包含所有成员
        if (contain)
            _value = 0xFFFFFFFF;
        else
            _value = 0;
    }

    //包含一个枚举,用模板传参而不用参数是为了
    //能在编释期确定值,提高效率
    template<T Value>
    void Include()
    {
        _value |= EnumValue<Value>::size;
    }

    //去掉一个枚举
    template<T Value>
    void Exclude()
    {
        _value &= EnumValue<Value>::nsize;
    }

    //判断是否包含一个枚举
    template<T Value>
    bool Has()
    {
        return _value & EnumValue<Value>::size;
    }

    //判断set是否是空的
    bool Empty()
    {
        return _value == 0;
    }
};

#endif//P_SET_H

-------------------------------------------分隔线--------------------------

测试代码:

#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<hasSystemMenu>();
    set.Include<hasMaximize>();
    set.Exclude<hasSystemMenu>();

    if (set.Has<hasSystemMenu>())
        cout << "hasSystemMenu" << endl;
    if (set.Has<hasMinimize>())
        cout << "hasMinimize" << endl;
    if (set.Has<hasMaximize>())
        cout << "hasMaximize" << endl;

    cin.get();
    return 0;
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值