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 would 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:
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;
}
// 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
C++ does have member variable pointers, but they're not used that often, and in any case they're not how you'd typically solve a problem of this sort.
I only glanced over the code, but I'll go ahead and mention that the typical solution is to use a sorting function such as std::sort(), and either implement the < operator for the type in question, or implement a custom comparator. (You'll want to use the latter method if the objects are stored by pointer or smart pointer; also, using a custom comparator is arguably more clear, since overloading the < operator for objects that wouldn't normally be 'less-than comparable' can be a little confusing.)
bool store( const 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;
}
// 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
Not sure if i understood but you could use inheritance and base all objects on a base class with that member? Like make the container take in a pointer to an object of type ContainsMyWeirdSortingVariable
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.
// This can be reused for any member variable type
template<typename T, typename MemberType>
struct memvar_compare : public std::binary_function<T, T, bool>
{
const MemberType T::*memvar_ptr;
memvar_compare(const MemberType T::* memvar_ptr) : memvar_ptr(memvar_ptr) { }
bool operator() (const T &lhs, const T &rhs) const
{
return (lhs.*memvar_ptr) < (rhs.*memvar_ptr);
}
};
for (std::set<person, person_compare>::const_iterator it = people.begin(), e = people.end(); it != e; ++it)
std::cout << it->name << ", age " << it->age << '\n';
While a std::map would actually insert the items in sorted order, as owl points out, the additional overhead of storing such small POD types in a map would almost certainly vastly outweigh this benefit.
Also, since when did this work? Have I missed something?
[source lang="c++"]
FoodItem *f = new FoodItem() { i, nNames, nPrices };
[/source]
It still sounds like you want a database. Have you considered such a solution?
What are your requirements if the value of the member changes over time?
Also, since when did this work? Have I missed something?
FoodItem *f = new FoodItem() { i, nNames, nPrices };
Looks like a C++0x initialiser list.
[/quote]
Thanks for everyones replies.
Yes a database would be best but I am using Mosync(Cross Platform Mobile API) & it has limitations. These limitations being, no SQL support (I can write it myself but I dont have time, it does have XML support tho), no STL support (it has its own Set, Queue, Stack, Vector & Maps tho), no threading & doesn't support C++ exceptions.
So to me the best alternative would be a templated container that can be arranged by an object's specific data member (I thought this was a pretty smart way to do this; write it once then use it in many apps). I will look into using the MAUtil::Set class for this tho.