Ниже приведены два варианта того, что вы запрашиваете: первое, в котором элемент является параметром шаблона, и второе, в котором элемент вместо этого передается в качестве аргумента при построении карты ...
#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 ++ карты. Вы можете решить во время выполнения, какой элемент вы хотите использовать в качестве ключа (вторая версия), но его тип должен быть зафиксирован во время компиляции.
Если вместо этого даже фактический член, который вы хотите использовать в качестве ключа, известен как время компиляции, тогда указатель члена может быть разложен как параметр шаблона (первая версия), генерируя более эффективный код (однако создавая новый класс для каждого другого member - таким образом увеличивая размер скомпилированного кода).