Hello
I have a Container class that will allow me to store & retrieve elements from it easily by using the member variables of the elements as their key/identifier.
My problem is I am tring to store a pointer to an objects member variable, but I get a compiler error. What am I doing wrong?
PS: do you have any advice on how I could improve my Container class; such as using const correctly & whether to hide the copy constructor?
This is how I use my container class:
#include <iostream>
#include "ObjectCollection.h"
using namespace std;
// Test items
struct FoodItem
{
unsigned int ID;
string name;
double price;
};
struct Order
{
unsigned int ID;
unsigned int personID;
};
int main()
{
Collection <FoodItem*, std::string> foodCol( &FoodItem::name );
Collection <Order*, unsigned int> orderCol( &Order::personID );
// Create some test objects
string nNames[] = {"a", "b", "c", "d"};
double nPrices[] = {1.1, 2.2, 3.3, 4.4};
unsigned int nPersonIDs[] = {6, 7, 8, 9};
for (int i=0; i<4; i++)
{
FoodItem *f = new FoodItem() { i, nNames[i], nPrices[i] };
Order *o = new Order() { i, nPersonIDs[i] };
foodCol.store( f );
orderCol.store( o );
}
// Test collection
if ( foodCol["a"]->ID == 0 )
{
cout << "Correctly retrieved a stored FoodItem by its name \n"
}
if ( foodCol[0]->name == "a" )
{
cout << "Correctly retrieved a stored FoodItem by its ID \n"
}
if ( foodCol[7]->ID == 1 )
{
cout << "Correctly retrieved a stored Order by its personID \n"
}
if ( foodCol[1]->personID == 7 )
{
cout << "Correctly retrieved a stored Order by its ID \n"
}
// Release dynamic memory
for (vector <FoodItem*> f=foodCol.getValues(); !f.empty(); f.pop())
{
delete f.back();
}
for (vector <Order*> o=orderCol.getValues(); !o.empty(); o.pop())
{
delete o.back();
}
system("PAUSE");
return 0;
}
My Container implementation:
#ifndef OBJECTCOLLECTION
#define OBJECTCOLLECTION
#include <vector>
#include <map>
template <typename Object, typename dataType>
class Collection
{
public:
Collection( dataType Object::*nMemberVariable )
{
memberVariable = nMemberVariable;
}
~Collection()
{
}
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() || instanceIntMap.find(o->ID) != instanceIntMap.end() )
{
return false;
}
instanceIntMap.insert( o->ID, o );
instanceVarMap.insert( o->*memberVariable, o );
return true;
}
Object* operator[] ( dataType nParam ) // should this be a const function? I never know when to use const in functions& where not to
{
return get(nParam);
}
Object* operator[] ( unsigned int nParam )
{
return get(nParam);
}
Object* get( 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* get( unsigned int nParam )
{
if ( instanceIntMap.find(nParam) == instanceIntMap.end() )
{
return NULL;
}
return instanceIntMap[ nParam ];
}
bool remove( Object *o )
{
// check we have o in our collection
if ( instanceIntMap.find(o->ID) == instanceIntMap.end() )
{
return false;
}
instanceIntMap.remove( o->ID );
instanceVarMap.remove( o->*memberVariable );
}
int size()
{
return instanceIntMap.size();
}
bool empty()
{
return instanceIntMap.empty();
}
std::vector <Object*> getValues()
{
std::vector <Object*> values( instanceIntMap.size() );
typename std::map <unsigned int, Object*>::iterator it = instanceIntMap.begin();
while ( it != instanceIntMap.end() )
{
values.add( (*it).second );
it++;
}
return values;
}
Object* front()
{
if ( instanceIntMap.empty() ) { return NULL; }
typename std::map <unsigned int, Object*>::iterator it = instanceIntMap.begin();
return (*it).second;
// can I just say... return (*instanceIntMap.begin()).second; // even if the map is empty?
}
Object* back()
{
if ( instanceIntMap.empty() ) { return NULL; }
typename std::map <unsigned int, Object*>::iterator it = instanceIntMap.end();
it--;
return (*it).second;
}
private:
dataType Object::* memberVariable;
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
// so should I use maps or unordered_maps?
// I haven't really worked with handling copy constructors
// But do you think its wise I make it private because I am storing pointers?
Collection( const Collection &c )
{
}
Collection( Collection &c )
{
}
Collection& operator =( const Collection &c )
{
}
Collection& operator =( Collection &c )
{
}
};
#endif // OBJECTCOLLECTION