存储对具有不同类的对象成员变量的引用

发布于 2024-11-07 01:03:12 字数 2368 浏览 0 评论 0原文

我正在尝试创建一个 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

I am trying to create a Container class where I can retrieve an object from the container by using that objects member variable as its identifier. But I get a compile error because I am trying to store a pointer(?)/reference to the objects member variable

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

喜你已久 2024-11-14 01:03:12

C++ 中不允许声明模板数据成员(不要与定义静态成员时使用的模板语法混淆)。实现这一目标的最佳方法是,

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

Declaring a template data member is not allowed in C++ (not to confuse with template syntax used while defining a static member). The best way to achieve is,

template <typename Object, typename dataType>  // <-- Add dataType here
class Container
{
     private:
         dataType Object::* memberVariable; // use 'dataType' simply
// ...
};
情定在深秋 2024-11-14 01:03:12
template <typename dataType>
dataType Object::* memberVariable; //  error 

声明一个tempate数据成员?这是 C++ 不允许的。我不能给你建议任何替代方案,因为我实际上不明白你到底想做什么。

为什么不首先尝试使用标准库提供的容器呢?您是否见过 std::vectorstd::liststd::map 等,以及来自 的泛型函​​数?算法>

template <typename dataType>
dataType Object::* memberVariable; //  error 

Declaring a tempate data member? That is not allowed by C++. And I cannot you suggest any alternative, because I don't actually understand what exactly you're trying to do.

Why don't you first try using containers provided by the Standard Library? Have you seen std::vector, std::list, std::map etc, along with generic functions from <algorithm>?

潇烟暮雨 2024-11-14 01:03:12

在下面,您所要求的内容有两种变体:第一个成员是模板参数,第二个成员在构建地图时作为参数传递......

#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++ 代码。您可以在运行时决定要用作键的成员(第二个版本),但其类型必须在编译时固定。

相反,如果您想要用作键的实际成员在编译时已知,则可以将成员指针分解为模板参数(第一个版本),从而生成更有效的代码(但是为每个不同的成员创建一个新类 - 因此增加编译代码的大小)。

In the following there are two variations of what you are asking for: the first in which the member is a template parameter, and the second in which the member is instead passed as argument when building the map...

#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;
}

Basically you need to move at least the member type out as a template parameter because that is needed to be able to generate the C++ code of the map. You can decide at runtime what is the member you want to use as key (second version), but its type must be fixed at compile time.

If instead even the actual member you want to use as key is known a compile time then the member pointer can be factored out as a template parameter (first version), generating more efficient code (however creating a new class for every different member - thus increasing compiled code size).

很快妥协 2024-11-14 01:03:12

您可以通过声明这样的成员类型来逃脱。

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

template<typename Object>
class Container
{
  typename Object::ObjectVariablePtrType memberVariable;
};

you can get away by declaring a member type like this.

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

template<typename Object>
class Container
{
  typename Object::ObjectVariablePtrType memberVariable;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文