开发者

Storing a pointer to an objects member variable

I have a problem that has been annoying me for a while & I have yet to come up with a solution. I would like to create a container class that stores objects & sorts them according to ONE of their member variable values. So if I have a class of Students (with the member variable int studentID), I want to store them in my Container class according to their studentID value in ascending order. I have made the container class a templated class so I can use for any class in any of my projects.

My problem with my Container class: I cannot store pointers of objects(for example Student objects). The problem more precisely is that I cannot store a reference(?) to an objects member variable (for example a reference/pointer to a Student's studentID variable).

This problem has been annoying me for ages & any information or advice w开发者_如何学编程ould be highly appreciated. Is there a way to make my below Container class store pointers to objects member variables? Is there a different way to create a container of objects that can be sorted by their member variables?

#include <iostream>

using namespace std;

template <typename Object, typename dataType>
class Collection
{
     public:

         Collection( dataType Object::*nMemberVariable )
         {
             memberVariable = nMemberVariable;
         }

         bool store( Object* o )
         {
              // check that o is not a NULL pointer & not already present in maps
              if ( o==NULL  ||  instanceVarMap.find(o->*memberVariable) != instanceVarMap.end() ) 
              { 
                   return false; 
              }

              instanceVarMap.insert( o->*memberVariable, o ); 
              return true;
         }

     private:  
         dataType Object::* memberVariable;
         std::map <dataType, Object*>     instanceVarMap;
};


struct FoodItem
{
    unsigned int ID;
    string name;
    double price;
};


int main()
{

    // I am attempting to store a pointer to an objects member variable
    // this is so I can create a custom container class(like a map or vector) that 
    // sorts its contents (which are FoodItem objects) according to their member variable values
    // so a container could sort all its elements according to a FoodItems ID value or name value

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

    string nNames[]           = {"a", "b", "c", "d"};
    double nPrices[]          = {1.1, 2.2, 3.3, 4.4};

    for (int i=0; i<4; i++)
    {
        FoodItem *f = new FoodItem() { i, nNames[i], nPrices[i] };
        foodCol.store( f );
    }

    // Note storing an ACTUAL object is possible with this class
    Collection <FoodItem*> foodCol( &FoodItem::name );  
    FoodItem f( 1, "a", 4 );
    foodCol.store( f ); 

    system("PAUSE");
    return 0;   
}


If I understand the question correctly, what you asked seems a set. std::set can take a predicate for sorting as the second template argument. If you prepare a predicate which compares the target member for sorting, the elements in the set will be sorted according to that member.
For example:

#include <set>

struct FoodItem {
    unsigned int ID;
    double price;
};

template< class C, class T, T C::* M >
struct member_comparator { // predicate
    bool operator()( C const* x, C const* y ) const { return x->*M < y->*M; }
};

int main() {
    FoodItem a = { 1, 2.5 }, b = { 2, 1.5 };
    // a set sorted by ID
    std::set< FoodItem*
            , member_comparator< FoodItem, unsigned, &FoodItem::ID > > s_ID;
    s_ID.insert( &a );
    s_ID.insert( &b );
    // a set sorted by price
    std::set< FoodItem*
            , member_comparator< FoodItem, double, &FoodItem::price > > s_price;
    s_price.insert( &a );
    s_price.insert( &b );
}

Here is a test on ideone.


First, your Collection is templated on two types: Object and dataType. However, you always only fill in the first like Collection <FoodItem*> foodCol(...). Change that too:

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

Next,

FoodItem f( 1, "a", 4 );
foodCol.store( f );

shouldn't compile. You're expecting an Object*, while Object is a FoodItem*, so in the end you're expecting a FoodItem**, but what you pass is a simple FoodItem. Change the definition of store so it simply takes a const Object& and pass it &f in the above example. Since Object is FoodItem*, your store will expect a FoodItem* const&, that is, a constant reference to a FoodItem* pointer. Exactly what we want.

The rest looks fine as far as I can see, especially the member data pointer is correct. But I might be overlooking something, it's very late here...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜