Pointers and STL find() function.

Started by
15 comments, last by Zakwayda 14 years, 4 months ago
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).
Advertisement
Use a functor template that does the dereferencing internally:

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:

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.

|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 MeshGearFox
    bool 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.
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 MeshGearFox
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.
I 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.

edit: I didn't realize you were the one who said both things! Hilarious.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

This topic is closed to new replies.

Advertisement