我正在尝试创建一个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 :(得分:1)
在C ++中不允许声明模板数据成员(不要与定义静态成员时使用的模板语法混淆)。最好的方法是,
template <typename Object, typename dataType> // <-- Add dataType here
class Container
{
private:
dataType Object::* memberVariable; // use 'dataType' simply
// ...
};
答案 1 :(得分:0)
template <typename dataType>
dataType Object::* memberVariable; // error
声明 tempate 数据成员?这是C ++不允许的。我不能建议任何替代方案,因为我实际上并不明白你究竟想要做什么。
为什么不首先尝试使用标准库提供的容器?您是否看到了std::vector
,std::list
,std::map
等以及来自<algorithm>
的通用函数?
答案 2 :(得分: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 ++代码。您可以在运行时决定要用作键的成员(第二个版本),但其类型必须在编译时修复。
如果相反,即使您想要用作键的实际成员也称为编译时间,则可以将成员指针作为模板参数(第一版)进行分解,从而生成更高效的代码(但是为每个不同的代码创建一个新类)成员 - 从而增加编译的代码大小。)
答案 3 :(得分:0)
你可以通过声明这样的成员类型来逃避。
struct MyObject
{
int Variable;
typedef int MyObject::* ObjectVariablePtrType;
};
template<typename Object>
class Container
{
typename Object::ObjectVariablePtrType memberVariable;
};