Re: STL and finding objects by name
On Apr 4, 9:37 am, Matthew Bucknall <m...@mattbucknall.com> wrote:
Hello,
Apologies if the answer to this is obvious, I have spent quite some time
trying to come up with a solution. I would like to use some sorted STL
container (maybe a set ?) to hold a bunch of named objects, that is,
objects that posses their own name. I then want to search for objects in
the container by name. Here is an example:
class Thing
{
public:
Thing(const std::string& name):
m_name(name)
{}
std::string get_name() const { return m_name; }
bool operator< (const Thing& rhs) const
{
return m_name < rhs.m_name;
}
private:
const std::string m_name;
};
std::set<Thing> things;
std::set<Thing>::iterator find_thing(const std::string& name)
{
// this won't work of course, but this hopefully illustrates
// what I want to do
return things.find(name);
}
My question is, how can named objects (such as Thing) be stored in an
STL container such that they can then be efficiently found by name?
Note, I want named objects to have direct access to their name so
storing objects in a std::map<std::string, Thing> is no good IMHO
because items contained in the map don't have access to their keys.
Regards,
Matt.
Actually the answer is far from obvious. And actually your code works
as is.
I think what you wanted to say was "How to I make a container of Thing
sorted by the name of Thing, without having to replicate the name for
each entry, nor having to create a Thing object to search by?"
There is no direct answer. My solution uses a level of indirection:
class Thing
{
public:
explicit Thing(const std::string& name):
m_name(name)
{}
std::string get_name() const { return m_name; }
private:
std::string m_name;
//lots more stuff....
friend struct ThingWrapper;
};
typedef boost::shared_ptr<Thing> ThingPtr;
struct ThingWrapper{
ThingWrapper(std::string const& arg):m_name(arg){}
ThingWrapper(ThingPtr const& arg):m_thing(arg){}
bool operator< ( ThingWrapper const& rhs) const
{
if(m_thing )
if(rhs.m_thing)
return m_thing->m_name < rhs.m_thing->m_name;
else
return m_thing->m_name < rhs.m_name;
return m_name<rhs.m_name;
}
std::string get_name()const{
if(m_thing)return m_thing->m_name;
return m_name;
}
ThingPtr get_thing()const{
return m_thing;
}
private:
std::string m_name;
ThingPtr m_thing;
};
std::set<ThingWrapper> things;
ThingPtr find_thing(const std::string& name)
{
std::set<ThingWrapper>::iterator f
=things.find(ThingWrapper(name));
if(f!=things.end())return f->get_thing();
return ThingPtr();
}
void foo(){
ThingPtr tmp(new Thing("C++"));
things.insert(ThingWrapper(tmp));
things.insert(ThingWrapper(ThingPtr(new Thing("Java"))));
things.insert(ThingWrapper(ThingPtr(new Thing("Ruby"))));
things.insert(ThingWrapper(ThingPtr(new Thing("Erlang"))));
ThingPtr tmp2=find_thing("C++");
assert(tmp->get_name()==tmp2.get_name());
}
So what is really being searched and sorted are ThingWrappers, and it
know when there is just a string or the full object.
Lance
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]