2011-05-14 98 views
6

我想創建一個Container類,我可以通過使用該對象成員變量作爲其標識符從容器中檢索對象。 但我得到一個編譯錯誤,因爲我想存儲指針(?)/參照對象的成員變量存儲對一個不同類的對象成員變量的引用

template <typename Object> 
class Container 
{ 
    private: 
     template <typename dataType> 
     dataType Object::* memberVariable; // error here "data member 'memberVariable' cannot be a member template" 

     template <typename dataType> 
     std::map <dataType, Object*>  instanceVarMap; // what would be more efficient; a Map or unordered_map? I heard that 
     std::map <unsigned int, Object*> instanceIntMap; // ...unordered_maps use more memory & Maps are better when integers are the keys 

    public; 
     template <typename dataType> 
     Collection(dataType Object::*nMemberVariable) 
     { 
      memberVariable = nMemberVariable; 
     } 

     template <typename dataType> 
     Object* operator[] (dataType nParam) 
     { 
      // do I need to check whether the element already exists or does 
      // stl already do this for me? 
      if (instanceVarMap.find(nParam) == instanceVarMap.end()) 
      { 
        return NULL; 
      } 

      return instanceVarMap[ nParam ]; 
     } 

     Object* operator[] (unsigned int nParam) 
     { 
      if (instanceIntMap.find(nParam) == instanceIntMap.end()) 
      { 
        return NULL; 
      } 

      return instanceIntMap[ nParam ]; 
     } 

     void store(Object* o) 
     { 
       if (o==NULL || instanceMap.contains(o->memeberVariable) != instanceMap.end()) { return; } 

       instanceIntMap.insert(o->ID, o); 
       instanceVarMap.insert(o->memberVariable, o); // is this the correct way I get the objects member variable? o->memberVariable 
     } 
}; 


// I am doing this so I can use the class like so 
struct FoodItem 
{ 
    unsigned int ID; 
    string name; 
    double price; 
}; 

Collection <FoodItem*> foodCol(&FoodItem::name); 

// after storing some FoodItems in foodCol, I can retreive a FoodItem either 
// by their ID or their name 
FoodItem* f = foodCol["coffee"]; // find FoodItem by their member variable 'name' 
FoodItem* g = foodCol[1];   // find FoodItem by their ID var 
+0

這是什麼:'集合 foodCol(&FoodItem :: name);'應該是什麼意思?什麼地址? – 2011-05-14 06:06:02

+0

我想你的意思是&FoodItem :: name是什麼意思,我指的是結構FoodItem的成員變量名稱。因此,我創建了一個Collection並且我希望能夠通過使用它們的名稱作爲關鍵字(標識符)來訪問它的FoodItem元素 – user593747 2011-05-14 06:09:19

回答

1

在C++中不允許聲明模板數據成員(不要與定義靜態成員時使用的模板語法混淆)。爲了達到最好的辦法是,

template <typename Object, typename dataType> // <-- Add dataType here 
class Container 
{ 
    private: 
     dataType Object::* memberVariable; // use 'dataType' simply 
// ... 
}; 
0
template <typename dataType> 
dataType Object::* memberVariable; // error 

聲明一個tempate數據成員?這是C++不允許的。我不能提出任何其他建議,因爲我實際上並不明白你想要做什麼。

爲什麼不首先嚐試使用標準庫提供的容器?你見過std::vector,std::list,std::map等,以及從<algorithm>的一般功能?

+0

什麼?我知道我可以這樣做int Object :: * memberVariable我不知道編譯時的memberVariable的數據類型,有什麼我可以做的嗎? – user593747 2011-05-14 06:10:56

+0

@ user593747:如果你不知道成員的數據類型,那麼在編譯時,你不能做你想做的事。 C++是一種靜態類型語言,這意味着每個變量的類型必須在編譯時已知。 – Nawaz 2011-05-14 06:13:52

+0

你可以......假設至少成員**類型**在編譯時已知。看到我的答案(第二種情況)。 – 6502 2011-05-14 06:38:38

0

在下面也有你問了兩個變化:第一,其中成員是一個模板參數,並在該成員,而不是作爲傳遞的第二建立參數時,地圖...

#include <map> 
#include <string> 
#include <iostream> 

template<typename Object, typename MemberType, MemberType Object::*member> 
struct MemberMap 
{ 
    std::map<MemberType, Object *> mmap; 

    Object * operator[](const MemberType& mv) const 
    { 
     typename std::map<MemberType, Object *>::const_iterator i = mmap.find(mv); 
     return i == mmap.end() ? NULL : i->second; 
    } 

    void store(Object *o) 
    { 
     if (o && mmap.find(o->*member) == mmap.end()) 
      mmap[o->*member] = o; 
    } 
}; 

template<typename Object, typename MemberType> 
struct MemberMapByInst 
{ 
    MemberType Object::*member; 
    std::map<MemberType, Object *> mmap; 

    MemberMapByInst(MemberType Object::*member) : member(member) 
    { 
    } 

    Object * operator[](const MemberType& mv) const 
    { 
     typename std::map<MemberType, Object *>::const_iterator i = mmap.find(mv); 
     return i == mmap.end() ? NULL : i->second; 
    } 

    void store(Object *o) 
    { 
     if (o && mmap.find(o->*member) == mmap.end()) 
      mmap[o->*member] = o; 
    } 
}; 

struct Foo 
{ 
    std::string name; 

    Foo(const std::string& name) : name(name) 
    { 
    } 
}; 

int main() 
{ 
    Foo foo1("This is a test"); 
    Foo foo2("This is another test"); 

    MemberMap<Foo, std::string, &Foo::name> namemap; 
    namemap.store(&foo1); 
    namemap.store(&foo2); 

    MemberMapByInst<Foo, std::string> namemap2(&Foo::name); 
    namemap2.store(&foo1); 
    namemap2.store(&foo2); 

    std::cout << (namemap["This is a test"] != NULL) << std::endl; 
    std::cout << (namemap["What about this?"] != NULL) << std::endl; 
    std::cout << (namemap2["This is a test"] != NULL) << std::endl; 
    std::cout << (namemap2["What about this?"] != NULL) << std::endl; 

    return 0; 
} 

基本上你需要移動至少成員作爲模板參數類型,因爲需要的就是能夠生成地圖的C++代碼。你可以在運行時決定你想用什麼作爲鍵(第二個版本),但是它的類型必須在編譯時修正。

如果相反,即使您想用作鍵的實際成員已知編譯時間,那麼成員指針也可以作爲模板參數(第一版本)分解出來,從而生成更高效的代碼(但爲每個代碼創建一個新類不同的成員 - 從而增加編譯的代碼大小)。

+0

有沒有辦法通過這種方法存儲指向對象的指針?所以我可以做這個MemberMap persistantObjectMap; – user593747 2011-05-21 03:22:45

0

你可以通過聲明這樣的成員類型逃脫。

struct MyObject 
{ 
int Variable; 
typedef int MyObject::* ObjectVariablePtrType; 
}; 

template<typename Object> 
class Container 
{ 
    typename Object::ObjectVariablePtrType memberVariable; 
}; 
相關問題