views:

467

answers:

6

I'm sure I'm making this harder than it needs to be.

I have a vector...

vector<Joints> mJointsVector;

...comprised of structs patterned after the following...

struct Joints
{
    string name;

    float origUpperLimit;
    float origLowerLimit;   
};

I'm trying to search mJointsVector with "std::find" to locate an individual joint by its string name - no luck so far, but the examples from the following have helped, at least conceptually:

http://stackoverflow.com/questions/589985/vectors-structs-and-stdfind

Can anyone point me further in the right direction?

+9  A: 

A straight-forward-approach:

struct FindByName {
    std::string name;
    FindByName(const std::string& name) : name(name) {}
    bool operator()(const Joints& j) { return j.name == name; }
};

std::vector<Joints>::iterator it = std::find_if(m_jointsVector.begin(), m_jointsVector.end(), FindByName("foo"));

if(it != m_jointsVector.end()) {
    // ...
}

Alternatively you might want to look into something like Boost.Bind to reduce the amount of code.

Georg Fritzsche
while this works, I think the operator() of a function object should always be const, just for flexibility. if one day you have a range of const Joints, the function object still works.
vividos
This only seems to work if I change "bool operator(" to "bool operator()(". Is this correct? I'm overwhelmed by how many ways there are to do this!
Monte
Oops, i missed the first parentheses - fixed.
Georg Fritzsche
@vividos: It already works with `const Joints` - i agree on the constness though.
Georg Fritzsche
gf - of course you're right, since j is already const
vividos
A: 
bool
operator == (const Joints& joints, const std::string& name) {
    return joints.name == name;
}

std::find(mJointsVector.begin(), mJointsVector.end(), std::string("foo"));
Andreas Brinck
A: 

You should be able to add a equals operator do your struct

struct Joints
{
    std::string name;

    bool operator==(const std::string & str) { return name == str; }
};

Then you can search using find.

tamulj
The equality operator should be reserved for use to test if two objects of the same type are equivalent. Only very rarely should you use it to compare with other types.
Martin York
Mind explaining why or cite a source that does?
tamulj
This simple short answer has many shortcommings: you should prefer free function operators over member function operators (symmetry with respect to types in some operations), if you overload == you should also overload !=, and finally as Martin pointed, when overloading an operator you should not change the semantics. The operator symbol implies some semantics to the reader, if those semantics are broken the possibility of errors in user code increases. Who could think that `a==b` would yield true for different objects?
David Rodríguez - dribeas
+5  A: 

how about:

std::string name = "xxx";

std::find_if(mJointsVector.begin(), 
             mJointsVector.end(), 
             [&s = name](const Joints& j) -> bool { return s == j.name; }); 
dman
Uh, what? This isn't yet supported :P (Even then, I think this is wrong.)
GMan
Its not wrong, its correct and in a couple of years time, this answer will be seen as being "more" correct when compared to the others.
dman
Darid, what do you mean? Why is this more correct? Not challenging you - I'm totally clueless actually - and curious.
Monte
@darid: Don't edit your answer *then* refute my statement! :P That's like virtual straw-man. It was wrong, but now it's definitely good. :]
GMan
@Monte: The other answers are what you need to do today. This feature, called "lambdas", are basically in-place functions. In essence, they create unnamed functors, similar to the other answers. But this keeps the logic close to the calling site, and is arguably more readible.
GMan
Though the anonymous function is a good idea, shouldn't you use `find_if`?
xtofl
David Rodríguez - dribeas
@GMan: jeeez you're too quick for me, i was hoping to go under the radar with that edit :>
dman
@dribeas: (1)The type is Joints not Joint (2) The comparison is correct - please read the code (3) Generally this is the direction C++ is going, people should start using these features instead of slopping around with vc6, vc8, vc9 gen compilers.
dman
So lambda support is not quite ubiquitous? Can anyone tell me if they're safe to use with OS X 10.6 or iPhone projects?
Monte
David Rodríguez - dribeas
@Monte: its a feature that will be in the next C++ standard that is not out yet. Current gcc versions support it when setting a flag, Visual Studio 2010 will also support them.
Georg Fritzsche
@Monte: if you can use g++ 4.5 or later you can try, but g++ 4.4 and before did not have lambda support. And then again, I would not try the latest addition into the compiler for production code until some time and testing has been performed.
David Rodríguez - dribeas
Ah! Thanks for the info!
Monte
A: 
struct Compare: public unary_function <const string&>
{
     public:
            Compare(string _findString):mfindString(_findString){}
            bool operator () (string _currString)
            {
                return _currString == mfindString ;
            }
     private:
            string mfindString ;
}

std::find_if(mJointsVector.begin(), mJointsVector.end(), Compare("urstring")) ;
hype
You never declared `_currString` or `_findString` and your inheritance is wrong (precise the template parameters)
Matthieu M.
Thanks for pointing that out. I have corrected it
hype
A: 
#include <boost/bind.hpp>

std::vector<Joints>::iterator it;

it = std::find_if(mJointsVector.begin(),
                  mJointsVector.end(),
                  boost::bind(&Joints::name, _1) == name_to_find);
Fred