仿照std::map定制一个Dictionary

来源:互联网 发布:java sleep 让出cpu 编辑:程序博客网 时间:2024/04/29 10:22

以前在做一个编译器的时候,碰到这样一个问题:编译器把所有的标识符(identifier)字符串存储在一个String Table中,其实就是一个std::vector<std::string>,便于用数字来引用,但是在查找时却要根据字符串来匹配,速度显然不行。于是我不得不自己编一个Dictionary,存储的是<__int64,Entry>值对,Entry是这个标识符的入口,而__int64则是该标识符在String Table中的索引,查找时也是根据string来比较的。这样既能保证查找的效率,又能保留标识符的索引。
现在趁还记得,写下来再说。
为简化情形,先假设已经定义的如下的类:

class Entry;

其内容不重要,意义就是标识符的入口。
自定义的类里面,最重要的就是一个Comparator类,这个类的作用是告诉我们的Dictionary,该如何比较传给它的参数:__int64和std::string。我把String Table作为模板参数__StrTbl,而__StrTbl::U8就是__int64。仿照标准库的代码,具体实现如下:

#include <map>

template<class __StrTbl>class Comparator
    :public std::binary_function<std::string,typename __StrTbl::U8,bool>
{
public:
    typedef typename __StrTbl::U8 U8;
    typedef std::binary_function<std::string,U8,bool> __MyBase;
    typedef typename __MyBase::first_argument_type first_argument_type;
public:
    ~Comparator(){}
    explicit Comparator(const __StrTbl & st):StrTbl_(st){}
    template<typename T1,typename T2>
        bool operator ()(const  T1 & left,const  T2 & right) const{
            return DataTrans(left) < DataTrans(right);
        }
    const __StrTbl & StrTable() const{
        return StrTbl_;
    }
private:
    const std::string & DataTrans(const std::string & val) const{return val;}
    const std::string & DataTrans(U8 index) const{return StrTbl_[index];}
private:
    const __StrTbl & StrTbl_;
};

注意到Comparator的构造函数必须要传const __StrTbl &,原因是很显然的。
然后就是operator ()()的传入参数类型,我都用模板参数,但是用DataTrans()来转化成__StrTbl里对应的字符串。其余的几个typedef和const函数就没什么的好说的了。

现在可以定义Dictionary类了,和Comparator类一样,它也需要一个模板参数__StrTbl,而。仿照标准库的map,实现如下:

#include "Comparator.h"
#include "Entry.h"

template<class __StrTbl>class Dictionary:
    public std::_Tree<
        std::_Tmap_traits<
            typename __StrTbl::U8,
            Entry,
            Comparator<__StrTbl>,
            std::allocator<std::pair<
                const typename __StrTbl::U8,
                Entry> >
            ,false
        >
    >
{
public:
    typedef typename __StrTbl::U1 U1;
    typedef typename __StrTbl::U4 U4;
    typedef typename __StrTbl::U8 U8;
    typedef Dictionary _Myt;
    typedef U8 key_type;
    typedef Entry mapped_type;
    typedef Entry referent_type;    // retained
    typedef Comparator<__StrTbl> key_compare;
    typedef std::_Tree<std::_Tmap_traits<key_type,mapped_type,key_compare,std::allocator<std::pair<const key_type,mapped_type> >,false> > _Mybase;
    typedef typename _Mybase::value_compare value_compare;
    typedef typename _Mybase::allocator_type allocator_type;
    typedef typename _Mybase::size_type size_type;
    typedef typename _Mybase::difference_type difference_type;
    typedef typename _Mybase::pointer pointer;
    typedef typename _Mybase::const_pointer const_pointer;
    typedef typename _Mybase::reference reference;
    typedef typename _Mybase::const_reference const_reference;
    typedef typename _Mybase::iterator iterator;
    typedef typename _Mybase::const_iterator const_iterator;
    typedef typename _Mybase::reverse_iterator reverse_iterator;
    typedef typename _Mybase::const_reverse_iterator const_reverse_iterator;
    typedef typename _Mybase::value_type value_type;
    //my declarations
    typedef typename key_compare::first_argument_type first_argument_type;
private:
    iterator Lower_bound(const first_argument_type & val)
    {    // find leftmost node not less than _Keyval in mutable tree
        return (_TREE_ITERATOR(_LBound(val)));
    }
    _Nodeptr _LBound(const first_argument_type & val) const
    {    // find leftmost node not less than _Keyval
        _Nodeptr _Pnode = _Root();
        _Nodeptr _Wherenode = _Myhead;    // end() if search fails
        while (!_Isnil(_Pnode))
            if (this->comp(_Key(_Pnode), val))
                _Pnode = _Right(_Pnode);    // descend right subtree
            else{    // _Pnode not less than _Keyval, remember it
                _Wherenode = _Pnode;
                _Pnode = _Left(_Pnode);    // descend left subtree
            }
            return (_Wherenode);    // return best remembered candidate
    }
public:
    ~Dictionary(){}
    explicit Dictionary(const __StrTbl & strtbl):_Mybase(key_compare(strtbl), allocator_type()),strTbl_(strtbl){}
    iterator Query(const first_argument_type & val){    // find an element in mutable sequence that matches val
        iterator _Where = Lower_bound(val);
        return (_Where == end() || this->comp(val, _Key(_Where._Mynode())) ? end() : _Where);
    }
    bool Has(const first_argument_type & val){
        return Query(val) != end();
    }
    template<class __Symbol>
        void AddEntry(const __Symbol & sym,U4 index,U4 subIndex){
            insert(value_type(sym.Text(),mapped_type(U1(__Symbol::SymType),index,subIndex)));
        }
private:
    const __StrTbl & strTbl_;
};

在AddEntry()里出现了几个新的类名,__Symbol是符号表类,U4和U1分别为unsigned long和unsigned __int8。
insert需要一个std::pair(U8,Entry),前者是sym.Text()的返回值,后者是mapped_type(U1(__Symbol::SymType),index,subIndex),其实就是Entry的构造函数,具体传的参数就与实际情况有关了。
时间紧,现在吃饭去了!

原创粉丝点击