2012-02-17 58 views
0
位置

關鍵單一性和排序上 http://msdn.microsoft.com/en-us/library/y1z022s1%28v=vs.80%29.aspx#_core_collection_shape_featuresMFC詞典收集與

看錶,我不能看到一個MFC集合爲目的,我需要。

http://msdn.microsoft.com/en-us/library/s897094z%28v=vs.80%29.aspx CMAP的文檔還指出

「你可能會認爲這是迭代由鍵值順序;它不是檢索元素的順序是不確定的」

正如我所期望的那樣,我認爲它使用哈希算法。

我需要什麼,是具有以下功能的詞典:

  • 排序(由一個int,例如) - 目的:交換順序的元素,也讓他們指出
  • 順序如下
  • 對我來說,這似乎甚至不需要成爲「真正的關鍵」 - 我真的不需要那些瘋狂的哈希算法來快速訪問。而且,按鍵訪問元素的問題,似乎我現在不需要,但是我只能在開始使用時才能安全地回答這個問題。
  • 不要需要快速插入,刪除,更新等
  • 不需要快速搜索指定的元素
  • 關鍵單一性

的我不知道有多少次我可以套用這個模式在真實應用程序中 什麼是您可以爲此建議我的最佳解決方案?

注意:我在C#中也遇到了同樣的問題,前一段時間。解決方案也是受歡迎的。如果我記得正確SortedDictionary是關鍵的排序,所以它不適合。

編輯:即使它會更可取 - 只是爲了不與現有的代碼庫不協調 - 使用MFC的東西,它不是一個義務。所以你可以建議你想要的任何東西,如果它是標準的C++。

EDIT2:爲了提高清晰度:容器中的每個元素的描述是

{ 
    int Unique NonNullable OrderIndex, 
    enum KeyEnum Unique NonNullable key, 
    enum ValueEnum NotUnique NonNullable value 
} 

如果就像這樣一個動態數組實現的,我真的不更在乎存儲OrderIndex 。對於這一個,我真的只需要一個指示相對位置的獨特值,並有可能交換位置元素。

由於提前,

塞爾吉奧

+0

甚至看這個圖http://stackoverflow.com/questions/471432/in-which-scenario-do-i-use-a-particular-stl-container我不能說什麼是最好的在我的問題中使用 – sergiol 2012-02-24 19:42:30

+0

一些有趣的辯論是在這裏進行:http://stackoverflow.com/questions/1504451/how-to-implement-a-multi-index-dictionary – sergiol 2012-02-26 14:59:48

回答

0

我決定從兩者的CMap和CARRAY派生一個模板類,並寫出如下ArrayMapTempl.h文件:

//Author: Sérgio Loureiro. This is open source. 

#include <afxtempl.h> 

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
class CArrayMap: protected CArray<KEY,ARG_KEY>, protected CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> 
{ 
private: 
    bool m_isChangingSize; 
public: 
    CArrayMap(): 
     m_isChangingSize(false) 
    { 
    }; 

    CArrayMap(const CArrayMap& src){}; 
    CArrayMap operator=(const CArrayMap& src){return *this;}; 

    // Attributes 
    INT_PTR GetSize() const; 
    INT_PTR GetCount() const; 
    BOOL IsEmpty() const; 
    INT_PTR GetUpperBound() const; 

    // Lookup 
    int Lookup(ARG_KEY key) const; 
    int Lookup(ARG_KEY key, VALUE& rValue) const; 

// Operations 
    // Clean up 
    void RemoveAll(); 

    // Accessing elements 
    const CPair& GetAt(INT_PTR nIndex) const; 
    CPair& GetAt(INT_PTR nIndex); 
    void SetAt(INT_PTR nIndex, ARG_KEY newKey, ARG_VALUE newValue); 
    const CPair& ElementAt(INT_PTR nIndex) const; 
    CPair& ElementAt(INT_PTR nIndex); 

    // Direct Access to the element data 
    const CPair& GetData() const; 
    CPair& GetData(); 

    // Potentially growing the array 
    INT_PTR Add(ARG_KEY newKey, ARG_VALUE newValue); 
    void Copy(const CArrayMap& src); 

    // overloaded operator helpers 
    const CPair& operator[](INT_PTR nIndex) const; 
    CPair& operator[](INT_PTR nIndex); 

    // Operations that move elements around 

    BOOL Swap(INT_PTR nIndex, INT_PTR nIndex2); 
    BOOL MoveUp(INT_PTR nIndex); 
    BOOL MoveDown(INT_PTR nIndex); 

    BOOL SwapByKey(ARG_KEY key, ARG_KEY key2); 
    BOOL MoveUpByKey(ARG_KEY key); 
    BOOL MoveDownByKey(ARG_KEY key); 

    BOOL InsertAt(INT_PTR nIndex, ARG_KEY newKey, ARG_VALUE newValue); 
    BOOL RemoveAt(INT_PTR nIndex); 
    BOOL RemoveByKey(ARG_KEY key); 


public: 
    void Serialize(CArchive&); 
#ifdef _DEBUG 
    void Dump(CDumpContext&) const; 
    void AssertValid() const; 
#endif 

#if 0 
public: 
// Construction 
    CArray(); 

// Attributes 
    INT_PTR GetSize() const; 
    INT_PTR GetCount() const; 
    BOOL IsEmpty() const; 
    INT_PTR GetUpperBound() const; 
    void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1); 

// Operations 
    // Clean up 
    void FreeExtra(); 
    void RemoveAll(); 

    // Accessing elements 
    const TYPE& GetAt(INT_PTR nIndex) const; 
    TYPE& GetAt(INT_PTR nIndex); 
    void SetAt(INT_PTR nIndex, ARG_TYPE newElement); 
    const TYPE& ElementAt(INT_PTR nIndex) const; 
    TYPE& ElementAt(INT_PTR nIndex); 

    // Direct Access to the element data (may return NULL) 
    const TYPE* GetData() const; 
    TYPE* GetData(); 

    // Potentially growing the array 
    void SetAtGrow(INT_PTR nIndex, ARG_TYPE newElement); 
    INT_PTR Add(ARG_TYPE newElement); 
    INT_PTR Append(const CArray& src); 
    void Copy(const CArray& src); 

    // overloaded operator helpers 
    const TYPE& operator[](INT_PTR nIndex) const; 
    TYPE& operator[](INT_PTR nIndex); 

    // Operations that move elements around 
    void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1); 
    void InsertAt(INT_PTR nStartIndex, CArray* pNewArray); 

// Implementation 
protected: 
    TYPE* m_pData; // the actual array of data 
    INT_PTR m_nSize;  // # of elements (upperBound - 1) 
    INT_PTR m_nMaxSize; // max allocated 
    INT_PTR m_nGrowBy; // grow amount 

public: 
    ~CArray(); 
    void Serialize(CArchive&); 
#ifdef _DEBUG 
    void Dump(CDumpContext&) const; 
    void AssertValid() const; 
#endif 
#endif 

//---------------------------------------------------------------------------------------- 
#if 0 
public: 
    // CPair 
    struct CPair 
    { 
     const KEY key; 
     VALUE value; 
    protected: 
     CPair(ARG_KEY keyval) : key(keyval) {} 
    }; 

protected: 
    // Association 
    class CAssoc : public CPair 
    { 
     friend class CMap<KEY,ARG_KEY,VALUE,ARG_VALUE>; 
     CAssoc* pNext; 
     UINT nHashValue; // needed for efficient iteration 
    public: 
     CAssoc(ARG_KEY key) : CPair(key) {} 
    }; 

public: 
// Construction 
    /* explicit */ CMap(INT_PTR nBlockSize = 10); 

// Attributes 
    // number of elements 
    INT_PTR GetCount() const; 
    INT_PTR GetSize() const; 
    BOOL IsEmpty() const; 

    // Lookup 
    BOOL Lookup(ARG_KEY key, VALUE& rValue) const; 
    const CPair *PLookup(ARG_KEY key) const; 
    CPair *PLookup(ARG_KEY key); 

// Operations 
    // Lookup and add if not there 
    VALUE& operator[](ARG_KEY key); 

    // add a new (key, value) pair 
    void SetAt(ARG_KEY key, ARG_VALUE newValue); 

    // removing existing (key, ?) pair 
    BOOL RemoveKey(ARG_KEY key); 
    void RemoveAll(); 

    // iterating all (key, value) pairs 
    POSITION GetStartPosition() const; 

    const CPair *PGetFirstAssoc() const; 
    CPair *PGetFirstAssoc(); 

    void GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const; 

    const CPair *PGetNextAssoc(const CPair *pAssocRet) const; 
    CPair *PGetNextAssoc(const CPair *pAssocRet); 

    // advanced features for derived classes 
    UINT GetHashTableSize() const; 
    void InitHashTable(UINT hashSize, BOOL bAllocNow = TRUE); 

// Implementation 
protected: 
    CAssoc** m_pHashTable; 
    UINT m_nHashTableSize; 
    INT_PTR m_nCount; 
    CAssoc* m_pFreeList; 
    struct CPlex* m_pBlocks; 
    INT_PTR m_nBlockSize; 

    CAssoc* NewAssoc(ARG_KEY key); 
    void FreeAssoc(CAssoc*); 
    CAssoc* GetAssocAt(ARG_KEY, UINT&, UINT&) const; 

public: 
    ~CMap(); 
    void Serialize(CArchive&); 
#ifdef _DEBUG 
    void Dump(CDumpContext&) const; 
    void AssertValid() const; 
#endif 
#endif 

}; 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline INT_PTR CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetSize() const 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return CArray::GetSize(); 
}; 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline INT_PTR CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetCount() const 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return CArray::GetCount(); 
} 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::IsEmpty() const 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return CArray::IsEmpty(); 
} 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline INT_PTR CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetUpperBound() const 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return CArray::GetUpperBound(); 
} 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline INT_PTR CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Add(ARG_KEY newKey, ARG_VALUE newValue) 
{ 
    VALUE rValue; 
    if(CMap::Lookup(newKey,rValue)) //already exists 
     return -1; 

    INT_PTR nIndex = CArray::m_nSize; //old size will be the new position 

    m_isChangingSize= true; 
    CMap::operator[] (newKey)= newValue; 
    CArray::Add(newKey); 
    m_isChangingSize= false; 

    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return nIndex; 
}; 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline const typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CPair& 
    CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAt(INT_PTR nIndex) const 
{ 
    ASSERT(nIndex >= 0 && nIndex < m_nSize); 
    if(nIndex >= 0 && nIndex < m_nSize) 
    { 
     return *CMap::PLookup(CArray::GetAt(nIndex)); 
    } 
    AfxThrowInvalidArgException(); 
}; 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
inline typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CPair& 
    CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAt(INT_PTR nIndex) 
{ 
    ASSERT(nIndex >= 0 && nIndex < m_nSize); 
    if(nIndex >= 0 && nIndex < m_nSize) 
    { 
     return *CMap::PLookup(CArray::GetAt(nIndex)); 
    } 
    AfxThrowInvalidArgException(); 
}; 

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
int CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key) const 
{ 
    VALUE rValue; 
    return this->Lookup(key, rValue); 
}; 

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
int CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key, VALUE& rValue) const 
{ 
    for (int i=0; i<m_nSize ;i++) 
    { 
     if(CArray::operator [] (i) == key && CMap::Lookup(key, rValue)) 
     { 
      return i; 
     } 
    } 
    return -1; 
}; 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
void CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll() 
{ 
    m_isChangingSize=true; 
    CMap::RemoveAll(); 
    CArray::RemoveAll(); 
    m_isChangingSize=false; 

    ASSERT(CArray::m_nSize == CMap::m_nCount); 
}; 



template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Swap(INT_PTR nIndex, INT_PTR nIndex2) 
{ 
    if(nIndex<0 || nIndex2<0) 
     return FALSE; 

    if(nIndex>=m_nSize || nIndex2>=m_nSize) 
     return FALSE; 

    //Swap with itself. Everything is fine and nothing needs to be done 
    if(nIndex == nIndex2) 
     return TRUE; 

    KEY k= CArray::GetAt(nIndex); 
    CArray::SetAt(nIndex, CArray::GetAt(nIndex2)); 
    CArray::SetAt(nIndex, k); 
}; 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::MoveUp(INT_PTR nIndex) 
{ 
    if (nIndex == 0) 
     return FALSE; 
    return Swap(nIndex,nIndex-1); 
}; 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::MoveDown(INT_PTR nIndex) 
{ 
    if (nIndex == m_nSize-1) 
     return FALSE; 
    return Swap(nIndex,nIndex+1); 
}; 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::SwapByKey(ARG_KEY key, ARG_KEY key2) 
{ 
    int nIndex= Lookup(key); 
    int nIndex2= Lookup(key2); 
    if(nIndex == -1 || nIndex2 == -1) 
     return FALSE; 

    return Swap(nIndex,nIndex2); 
} 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::MoveUpByKey(ARG_KEY key) 
{ 
    int nIndex= Lookup(key); 
    if(nIndex == -1) 
     return FALSE; 

    return MoveUp(nIndex); 
} 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::MoveDownByKey(ARG_KEY key) 
{ 
    int nIndex= Lookup(key); 
    if(nIndex == -1) 
     return FALSE; 

    return MoveDown(nIndex); 
} 



template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
int CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::InsertAt(INT_PTR nIndex,ARG_KEY newKey, ARG_VALUE newValue) 
{ 

    AssertValid();   //ASSERT_VALID(this); 

    if(nIndex < 0) 
     return FALSE; //AfxThrowInvalidArgException(); 

    if(nIndex > m_nSize) //doesn't make sense to grow more than last+1 , given newKey has to be unique 
     return FALSE; 

    //I am not using this->Lookup(ARG_KEY key), because I 
    //presume CMap::Lookup(ARG_KEY key, VALUE& rValue) will be faster, 
    //as it does not need to traverse the array.  

    VALUE rValue; 
    if(CMap::Lookup(newKey,rValue)) //already exists 
     return FALSE; 

    m_isChangingSize=true; 
    CMap::operator[] (newKey)= newValue; 
    CArray::InsertAt(nIndex,newKey,1); 
    m_isChangingSize=false; 

    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    return TRUE; 
} 


template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAt(INT_PTR nIndex) 
{ 
    if(nIndex<0 || nIndex>= m_nSize) 
     return FALSE; 

    KEY k= CArray::GetAt(nIndex); 

    //I am not using this->Lookup(ARG_KEY key), because I 
    //presume CMap::Lookup(ARG_KEY key, VALUE& rValue) will be faster, 
    //as it does not need to traverse the array.  

    VALUE rValue; 
    if(CMap::Lookup(k,rValue)) //already exists 
    { 
     m_isChangingSize= true; 
     CMap::RemoveKey(k); 
     CArray::RemoveAt(nIndex); 
     m_isChangingSize= false; 

     ASSERT(CArray::m_nSize == CMap::m_nCount); 
     return TRUE; 
    } 
    else 
     return FALSE; 
}; 

template <class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
BOOL CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveByKey(ARG_KEY key) 
{ 
    int nIndex= Lookup(key); 
    if(nIndex == -1) 
     return FALSE; 

    KEY k= CArray::GetAt(nIndex); 

    return RemoveAt(nIndex); 
}; 


template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
void CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Serialize(CArchive& ar) 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 
    //ASSERT_VALID((const CArray *)this); 
    //ASSERT_VALID((const CMap *)this); 

    CObject::Serialize(ar); 

    if (ar.IsStoring()) 
    { 
     ar.WriteCount(m_nSize); 
     if (m_nSize == 0) 
      return; // nothing more to do 

     for(INT_PTR i=0;i<m_nSize;i++) 
     { 
      KEY* pKey; 
      VALUE* pValue; 
      /* 
      * in some cases the & operator might be overloaded, and we cannot use it to 
      * obtain the address of a given object. We then use the following trick to 
      * get the address 
      */ 
      pKey = reinterpret_cast< KEY* >(&reinterpret_cast< int& >(const_cast< KEY& > (static_cast< const KEY& >(CArray::operator[](i))))); 
      pValue = reinterpret_cast< VALUE* >(&reinterpret_cast< int& >(static_cast< VALUE& >(CMap::operator[](*pKey)))); 
      SerializeElements<KEY>(ar, pKey, 1); 
      SerializeElements<VALUE>(ar, pValue, 1); 
     } 
    } 
    else 
    { 
     DWORD_PTR nNewCount = ar.ReadCount(); 
     while (nNewCount--) 
     { 
      KEY newKey[1]; 
      VALUE newValue[1]; 
      SerializeElements<KEY>(ar, newKey, 1); 
      SerializeElements<VALUE>(ar, newValue, 1); 
      this->Add(newKey[0], newValue[0]); //includes checking if it already exists 
     } 
    } 
} 

#ifdef _DEBUG 
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
void CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Dump(CDumpContext& dc) const 
{ 
    ASSERT(CArray::m_nSize == CMap::m_nCount); 

    CObject::Dump(dc); 

    dc << "with " << m_nSize << " elements"; 
    if (dc.GetDepth() > 0) 
    { 
     // Dump in format "[key] -> value" 
     KEY key[1]; 
     VALUE val[1]; 

     POSITION pos = GetStartPosition(); 
     while (pos != NULL) 

     for (int i=0; i<m_nSize; i++) 
     { 
      key[0]= CArray::operator[](i); 

      //val[0]= CMap::operator[](key[0]); 
      CMap::Lookup(key[0], val[0]); 

      dc << "\n\t["; 
      DumpElements<KEY>(dc, key, 1); 
      dc << "] = "; 
      DumpElements<VALUE>(dc, val, 1); 
     } 
    } 

    dc << "\n"; 
} 

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> 
void CArrayMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::AssertValid() const 
{ 
    CArray::AssertValid(); 
    CMap::AssertValid(); 

    if(!m_isChangingSize) 
     ASSERT(CArray::m_nSize == CMap::m_nCount); 
} 

#endif //_DEBUG 

現在我有我需要的一切。我沒有測試所有的東西,但我相信如果需要的話,只需要很少的更正。

無論如何,謝謝大家的答案和評論。

1

MFC不提供一個容器,做你所需要的,但你可以使用std::mapstd::set代替。每個將保持密鑰的獨特性;您選擇哪種方式取決於您希望將密鑰從有效負載分離還是集成到單個對象中。

0

當您說'已命令'時,您已經間接暗示'訂單索引'是唯一的'鑰匙'。爲什麼你不能使用std :: vector?

如果你想擁有另一個唯一的關鍵字,你可以使用std :: map,但是你將不得不作爲鍵/值組合的一部分即興創作'訂單'。我看到最終的解決方案將是複合材料。你將有你自己的類來支持你想要的東西,可以使用std :: map來實現這個或任何其他包含像列表一樣的東西。

+0

評論提高人們傳達的清晰度:我希望KeyEnum和OrderIndex都具有唯一性;和NO,我不希望對的唯一性,但每一個都是唯一的。 – sergiol 2012-02-25 01:10:07

0

在C++ Freenode上的IRC頻道這次談話之後,我覺得很想試試Boost多指數(zxvf是我):

zxvf   hello 
zxvf   I was trying to solve the problem of this question: http://stackoverflow.com/questions/9329011/mfc-dictionary-collection-with-key-unicity-and-ordering-by-position/9438561#9438561 
zxvf   what kind of container would you recommend to me? 
TinoDidriksen std::vector sounds fitting. 
zxvf   you can not guarantee unicity of keyEnum, TinoDidriksen 
MrBar  zxvf: so use std::map then 
zxvf   MrBar: I think you all didn't get the point of the problem 
evilissimo I think you'd need something like boost multi_index 
zxvf   I want both unicity of KeyEnum and OrderIndex 
MrBar  zxvf: i get point, but that container u asked about not exist 
TinoDidriksen zxvf, Boost.Multi_index then. 
evilissimo zxvf, by unicity you mean that there are at no given time two of any of them in the container? 
evilissimo or by the combination? 
MrBar  zxvf: u need to use intermix of containers 
zxvf   and NO, I don't want unicity of the pair <OrderIndex, KeyEnum> but unicity of each one 
evilissimo zxvf, had to ask 
       zxvf seeing what the heck is Boost Multi index 
MrBar  zxvf: noooo, not see in boost there no back way 
zxvf   MrBar, could you rephrase please? 
zxvf   Not english native speaker, me 
evilissimo zxvf, that wasn't even valid english 
MrBar  zxvf: hmm i too 
evilissimo zxvf, basically there are tons of useful stuff in boost, and usually once you start loving one library you start using more of them 
zxvf   thanks, people. It's aready late here and I will not see this tonight. But seems to me that Boost Multi index is a very good help for me 
+0

這篇文章似乎至少有趣:http://drdobbs.com/184401843 – sergiol 2012-02-26 14:38:29

+0

對C#有人設法做一個像Boost Multi索引的東西的Sems:http://www.codeproject.com/Articles/18864/Multi- Index-Container-for-C-2-0。似乎不那麼強大。 – sergiol 2012-02-26 14:51:08

+0

對於C#也有一個gui,就像完成了一個MultiKeyDictionary:http://www.codeproject.com/Articles/32894/C-Multi-key-Generic-Dictionary – sergiol 2012-02-26 15:03:43

0

使用一個陣列和陣列中的索引存儲爲你的價值的元素。如果需要,可以使用另一個CMap進行快速哈希訪問。我知道並聆聽過的地圖都不支持訂單索引編號。

+0

我在做的是一個具有多重繼承的類CArray和CMap。這是實踐,只缺乏最糟糕的部分:測試它。 – sergiol 2012-03-01 01:47:07