連想コンテナ(7)
現時点でのコード.連想コンテナ(2)と対して変わらないような.
内部で使うツール類
templatestruct TypeTraits { typedef T& ParamType; }; template struct TypeTraits { typedef T* ParamType; }; template<> struct TypeTraits { typedef int ParamType; }; // ポインタなら削除.ポインタでなければ削除しない. template struct PtrDeletor { inline static void deletor(DataParamType d, KeyParamType k) { }}; template struct PtrDeletor { inline static void deletor(DataParamType* d, KeyParamType* k) { delete d; delete k;} }; template struct PtrDeletor { inline static void deletor(DataParamType* d, KeyParamType k) { delete d;} }; template struct PtrDeletor { inline static void deletor(DataParamType d, KeyParamType* k) { delete k;} }; // 常に何もしない template struct NoneDeletor { inline static void deletor(DataParamType d, KeyParamType k) { }}; // 比較関数 // 特殊化する場合,元のkeyが(ポインタ|int)以外の場合は自動的に&がつくことに注意. template< typename Key> struct DefaultCompare { inline static bool less( const Key k0, const Key k1) { return k0<k1;} inline static bool equals( const Key k0, const Key k1) { return k0==k1;} };
本体
template< typename T , typename Key = int , templateclass Compare = DefaultCompare , template class Deletor = PtrDeletor > class AssocVector { private: typedef T DataType; typedef Key KeyType; typedef typename TypeTraits ::ParamType DataParamType; typedef typename TypeTraits ::ParamType KeyParamType; // 使いやすくするための省略形 typedef std::pair Item; typedef std::vector< Item> List; typedef typename List::iterator Iterator; typedef typename Compare CompImpl; typedef typename Deletor DelImpl; List v; // 同じkeyに何度もfindImplを掛けないようにキャッシュを持ってみる // IsExist()をしてからGet()を呼ぶ場合,二重に探索をすること避ける. // keyのコピーコンストラクタが重い場合はキャッシュを使わないほうがいい bool flagCache; Iterator itCache; KeyType keyCache; struct Compare { inline bool operator()(const Item& i0, const Item& i1) const {return CompImpl::less(i0.first,i1.first);} inline bool operator()(const Item& i, const Key k) const {return CompImpl::less(i.first,k);} inline bool operator()(const Key k,const Item& i) const {return CompImpl::less(k,i.first);} }; Iterator findImpl( const KeyParamType key) { if (!flagCache || !CompImpl::equals( keyCache, key)) { itCache = std::lower_bound( v.begin(), v.end(), key, Compare() ); flagCache = true; keyCache = key; } return itCache; } inline bool isFound( const KeyParamType key, const Iterator it) { return (it!=v.end() && CompImpl::equals( it->first, key)); } DataType dummyResult; public: AssocVector() : flagCache(false), dummyResult() {} ~AssocVector() {} void SetDefault( DataType init) { dummyResult = init; } void Insert( KeyParamType key, DataParamType data) { Iterator it = findImpl(key); if (isFound( key, it)) { // 同じkeyが存在するので上書きする // 削除処理を呼び出す DelImpl::deletor( it->second, it->first); it->first = key; // キーもdeletorに削除される可能性がある. it->second = data; } else { v.insert( it, Item(key, data)); flagCache = false; } } bool IsEmpty() { return v.empty(); } bool IsExist( KeyParamType key) { Iterator it = findImpl(key); return isFound( key, it); } DataParamType Get( KeyParamType key) { Iterator it = findImpl(key); if (isFound( key, it)) { return it->second; } return dummyResult; // ダミーを返す } bool Remove( KeyParamType key) { Iterator it = findImpl(key); if (isFound( key, it)) { // 削除処理を呼び出す DelImpl::deletor( it->second, it->first); v.erase( it); flagCache = false; return true; } return false; } void Clear() { // 削除処理を呼び出す for( Iterator it = v.begin(); it!=v.end(); ++it) { DelImpl::deletor( it->second, it->first); } v.clear(); flagCache = false; } };