Pointers and STL find() function.
Let's say I have a class XYZ, and a list of pointers to objects of class XYZ.
So, list<XYZ*> myList;
I want to look through this list for a specific XYZ object. So:
XYZ *test;
list<XYZ*>::iterator it;
it = find(myList.begin(), myList.end(), test);
However, that doesn't search for equivalent objects. It searches fore equivalent pointers.
So, if it's even possible, how would I use find on a list of pointers to look for the actual object that's being pointed to?
I tried find(*(myList).begin(), *(myList).end(), *test), which didn't give me any compiler errors, but it = couldn't handle it (I'm guessing either because it returned the wrong kind of iterator, or the pointer wizardry there is completely wrong).
Use a functor template that does the dereferencing internally:
If you don't want to supply the template argument yourself, you can build a helper function:
[Edited by - DevFred on December 4, 2009 5:16:50 AM]
template<typename T>class dereference{ T* pointer;public: dereference(T* p) : pointer(p) {} bool operator()(T* p) { return *p == *pointer; }};// ...it = find_if(test.begin(), test.end(), dereference<XYZ>(test));
If you don't want to supply the template argument yourself, you can build a helper function:
template<typename T>class dereference_t{ T* pointer;public: dereference_t(T* p) : pointer(p) {} bool operator()(T* p) { return *p == *pointer; }};template<typename T>dereference_t<T> dereference(T* p){ return dereference_t<T>(p);}// ...it = find_if(test.begin(), test.end(), dereference(test));
[Edited by - DevFred on December 4, 2009 5:16:50 AM]
The facility DevFred outlined is available in the boost lambda library. Something like this should do the trick:
EDIT: alternatively, just use std::list<XYZ> rather than hold the objects by pointer. You seem to be early on in the game as far as your C++ career is concerned, so I feel obliged to point out that this would usually be considered as a more normal thing to do.
using boost::lambda::_1;it = std::find_if(b, e, *_1 == *myXYZ);
EDIT: alternatively, just use std::list<XYZ> rather than hold the objects by pointer. You seem to be early on in the game as far as your C++ career is concerned, so I feel obliged to point out that this would usually be considered as a more normal thing to do.
All objects of type XYZ are created at run time. Wouldn't I need it to be a list of pointers so that I could use new..?
Anyway, just for testing purposes, I posted your functor code verbatim and changed the find arguments.
So, declaration for the objects, here:
const list<SpriteSheet*> &artAssets (This is an argument, of course)
list<SpriteSheet*>::const_iterator ait;
SpriteSheet *test;
And calling find:
ait = find(artAssets.begin(), artAssets.end(), dereference<SpriteSheet>(test));
Is still giving me the following errors, which I would get a result of just passing in *test.
And I do have operator == overloaded on the SpriteSheet class, although maybe I did that wrong:
So, uh, what am I doing wrong..?
--edit--
Getting the same issue with the boost::lambda thing.
[Edited by - MeshGearFox on December 4, 2009 12:01:17 PM]
Anyway, just for testing purposes, I posted your functor code verbatim and changed the find arguments.
So, declaration for the objects, here:
const list<SpriteSheet*> &artAssets (This is an argument, of course)
list<SpriteSheet*>::const_iterator ait;
SpriteSheet *test;
And calling find:
ait = find(artAssets.begin(), artAssets.end(), dereference<SpriteSheet>(test));
Is still giving me the following errors, which I would get a result of just passing in *test.
|n function `_InputIterator std::find(_InputIterator, _InputIterator, const _Tp&, std::input_iterator_tag) [with _InputIterator = std::_List_const_iterator<SpriteSheet*>, _Tp = dereference<SpriteSheet>]':instantiated from `_InputIterator std::find(_InputIterator, _InputIterator, const _Tp&) [with _InputIterator = std::_List_const_iterator<SpriteSheet*>, _Tp = dereference<SpriteSheet>]'error: no match for 'operator==' in '(&__first)->std::_List_const_iterator<_Tp>::operator* [with _Tp = SpriteSheet*]() == __val'
And I do have operator == overloaded on the SpriteSheet class, although maybe I did that wrong:
bool operator==(const SpriteSheet &rhs) const { if (this->sheetName == rhs.sheetName) { return true; } else { return false; } }
So, uh, what am I doing wrong..?
--edit--
Getting the same issue with the boost::lambda thing.
[Edited by - MeshGearFox on December 4, 2009 12:01:17 PM]
Quote:Original post by MeshGearFox
All objects of type XYZ are created at run time. Wouldn't I need it to be a list of pointers so that I could use new..?
No, observe:
list<pair<int, double> > myList;// function style constructor, template parameters necessarymyList.push_back(pair<int, double>(42, 42.0));// helper function, no need for template parametersmyList.push_back(make_pair(42, 42.0));
Quote:Original post by MeshGearFox
And calling find:
You need to call find_if, not find.
Quote:Original post by MeshGearFoxbool operator==(const SpriteSheet &rhs) const { if (this->sheetName == rhs.sheetName) { return true; } else { return false; } }
No need for the if/else, the result of the comparison is already the result you are interested in:
bool operator==(const SpriteSheet &rhs) const{ return this->sheetName == rhs.sheetName;}
Ahh, thank you. Didn't see the _if there, for whatever reason.
As for your second example, I guess I just admit the new command. I was... not aware that I could do that! Interesting! I'll go restructure some things real quick here.
As for your second example, I guess I just admit the new command. I was... not aware that I could do that! Interesting! I'll go restructure some things real quick here.
Quote:Original post by MeshGearFox
I guess I just admit the new command. I was... not aware that I could do that!
You probably have a programming background in programming languages where new is the only way to create an object (Java for example).
Quote:As for your second example, I guess I just admit the new command.
Brief addendum: I have absolutely no idea what this means, or what it was supposed to mean.
Also, this in general involved way too much fiddling around. See, the objects have a string name member that store's the strings name, and then a public accessor. What I WANTED to do was search through my list of objects based on the string name, which doesn't really work with find, and would work with find_if if I screwed around with the lambda functions a bit.
Or, the other option was to just look up the STL source code for the find functions, copy them into one of my own headers, and change them to do what I wanted. Which took all of five minutes.
And now I feel stupid :)
[Edited by - MeshGearFox on December 4, 2009 10:23:25 PM]
On a side note, why are you storing pointers to the objects rather than the objects themselves? There are very few good reasons to do that.
Quote:Original post by MeshGearFoxI figured it meant he liked doing return this->sheetName == rhs.sheetName; better than the if/else. That is a strange way to say it if that is what he meant though.Quote:As for your second example, I guess I just admit the new command.
Brief addendum: I have absolutely no idea what this means, or what it was supposed to mean.
edit: I didn't realize you were the one who said both things! Hilarious.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement