Martin wrote:
Quote:
Hi
>
I need to maintain a <setof pointers to objects, and it must be
sorted based on the values of pointed objects, not pointer values. I
can achieve this easily by defining my own comparing predicate for the
<set>. Here is an example:
>
#include <string>
#include <set>
using namespace std;
>
class A
{
public:
A(const string& Name): m_Name(Name) {}
const string& Name() const { return m_Name; }
>
private:
string m_Name;
>
// Other members
// ...
};
>
class ptr_less
{
public:
bool operator()(const A* lhs, const A* rhs) const
{
return lhs->Name() < rhs->Name();
}
};
>
int main()
{
const string Names[] = { "alpha", "omega", "gamma", "beta",
"epsilon" };
>
// Create objects and fill 'S'
set<A*, ptr_lessS;
for (unsigned i = 0; i < sizeof(Names)/sizeof(Names[0]); ++i)
S.insert(new A(Names[i]));
>
// Use 'S' ...
>
// Delete objects in 'S'
set<A*, ptr_less>::const_iterator csi;
for (csi = S.begin(); csi != S.end(); ++csi)
delete *csi;
};
>
In this example pointers in the <setS will be sorted according to the
ascending order of names of pointed objects.
>
Now I want to find an obect in 'S' with name "gamma". How must I do
that? One way is to construct a dummy object with that name, and pass
its address to 'find' method of <set>. Here is an example:
>
A tempA("gamma");
S.find(&tempA);
>
Everything works ok, but creating a dummy object only for searching
purposes looks somewhat silly. Isn't there an elegant way to accomplish
this?
No, you need the dummy. Whats more, is you need op==(...).
Which can get nasty if you...say...use smart pointers.
Thankfully, boost::shared_ptr is equipped with an op== overload to
pointee.
So load the dummy into a smart pointer. and voila!
Another option is a std::map< A, shared_ptr<A in which case the key
can uses the default predicate. If i were you, i'ld go that way.
#include <iostream>
#include <set>
#include <iterator>
#include <boost/shared_ptr.hpp>
class A
{
std::string m_Name;
public:
A(const std::string& Name): m_Name(Name) {}
A(const A& copy) { m_Name = copy.m_Name; }
const std::string& Name() const { return m_Name; }
friend std::ostream&
operator<<(std::ostream& os, const A& r_a)
{
return os << r_a.m_Name;
}
};
typedef boost::shared_ptr< A SharedPtrA;
class ptr_less
{
public:
bool operator()(const SharedPtrA& lhs,
const SharedPtrA& rhs) const
{
return lhs->Name() < rhs->Name();
}
};
int main()
{
const char* Names[] = { "alpha",
"omega",
"gamma",
"beta",
"epsilon" };
// Create objects and fill 'S'
std::set< SharedPtrA, ptr_less S;
for (size_t i = 0; i < sizeof(Names)/sizeof(*Names); ++i)
{
A a(Names[i]);
S.insert( SharedPtrA(new A(a)) );
std::cout << a << std::endl;
}
typedef std::set< SharedPtrA, ptr_less >::iterator SIter;
SIter siter = S.find(SharedPtrA(new A("gamma")));
if(siter != S.end())
{
std::cout << "found = " << *(*siter);
std::cout << " at " << *siter << std::endl;
}
else
{
std::cout << "name not found!\n";
}
}
/*
alpha
omega
gamma
beta
epsilon
found = gamma at 0x5051a0
*/