   How to to this via C++ std and/or boost [SOLVED]
  Ok, let's say we have a complex structure such asstruct something{  std::string strName;  //...irrelevant};Is it possible to do something like this for std::*_if family if functionsstd::vector<something> vec;std::string strSearch("");std::find_if(vec.begin(), vec.end(), _1->strName == strSearch);[Edited by - Toni Petrina on May 30, 2006 7:21:34 AM]
Quote:Original post by Toni PetrinaOk, let's say we have a complex structure such asstruct something{  std::string strName;  //...irrelevant};Is it possible to do something like this for std::*_if family if functionsstd::vector<something> vec;std::string strSearch("");std::find_if(vec.begin(), vec.end(), _1->strName == strSearch);The easiest way would probably be to overload operator==() for 'something' and std::string, if you feel it's appropriate and sufficiently unambiguous; this would allow you to just use std::find() directly.std::find_if() may however be more expressive of your intent; for this function and other *_if() functions you'll need a functor or function wrapper for the third argument. If you need help with any of that, you should have no trouble getting the info you need on this forum; just ask :-)[Note: It's late, and the above may have errors or be total nonsense...]   ;  I know how to write my own predicate but I was wondering could lambda functions solve this easier. After all, this is perfect example of their would-be-nice-to-have use.[lol]   ;Quote:Original post by Toni PetrinaI know how to write my own predicate...Oops, sorry about that :-| Guess I didn't read the question very well...   ;  From the boost::lambda library's documentationQuote:Some operators cannot be overloaded at all (::, ., .*). For some operators, the requirements on return types prevent them to be overloaded to create lambda functors. These operators are ->., ->, new, new[], delete, delete[] and ?: (the conditional operator).You can get around this limitation with the ->* operator though, like this:std::find_if(vec.begin(), vec.end(), (&_1 ->* &something::strName) == strSearch);If you have a vector of pointers the &_1 would obviously be just _1.   ;  Another way, using bind:std::find_if(vec.begin(), vec.end(), boost::bind(&something::strName, _1) == strSearch);   ;  EDIT:Actually, it doesn't work.I tried something like this although it is brokenstruct something{std::string strName;std::string getName(){return strName;}};template <typename _CompareType, typename _Pred>struct aux_dispatch{typedef bool result_type;template <typename _IncomingType, class _Member, class _Dereference>bool operator()(const _CompareType &ref1, _Member m, _Dereference d, _IncomingType refIterator){// first dereference iteratorsomething *s = boost::bind(d, refIterator)();// then get member_CompareType &c = s->*m;// finally comparereturn _Pred()(ref1, c);}};int _tmain(){std::vector<something> vec;std::string strSearch;std::find_if(vec.begin(), vec.end(), boost::bind(aux_dispatch<std::string, std::equal_to<std::string> >(), strSearch, &something::strName, &std::vector<something>::iterator::operator->, &_1));return 0;}Any ideas?[Edited by - Toni Petrina on May 30, 2006 6:14:15 AM];  Finally, solution isnamespace detail{template <typename _Type> struct aux_equal_to: public std::binary_function<_Type, _Type, bool>{bool operator()(const _Type &ref1, const _Type &ref2){return _tcscmp(ref1.c_str(), ref2.c_str()) == 0;}};};template <typename _Pred> struct aux_dispatch{typedef typename _Pred::first_argument_type argument_type;typedef bool result_type;template <typename _IncomingType, typename _Member>result_type operator()(const argument_type &ref1, _Member m, const _IncomingType &refIterator){return _Pred()(ref1, refIterator.*m);}};You can use it like thisstd::vector<something> vec;vec.push_back(something());std::string strSearch = "world";std::vector<something>::iterator it = std::find_if(vec.begin(), vec.end(), boost::bind(aux_dispatch<detail::aux_equal_to<std::string> >(), strSearch, &something::strName, _1));There is problem using std::equal_to.   ;  Such verbosity is unneccessary.  Not to mention that identifiers beginning with an underscore followed by a capital letter are reserved by the C++ standard for compiler and standard library writers, so you should not use them.#include <algorithm>#include <iostream>#include <stdexcept>#include <string>#include <vector>#include <boost/lambda/bind.hpp>#include <boost/lambda/lambda.hpp>struct something{std::string strName;std::string getName() const{return strName;}};bool find(std::vector< something > const & vec, std::string searchValue){using namespace boost::lambda;std::vector< something >::const_iterator i = std::find_if(vec.begin(), vec.end(), bind(&something::getName, _1) == searchValue);if (i == vec.end()){return false;}if (i->getName() != searchValue){throw std::runtime_error("find1 failed");}return true;}int main(){std::vector<something> vec;something a, b;a.strName = "first something";b.strName = "second something";vec.push_back(a);vec.push_back(b);std::cout << "testing find1\n";std::cout << "first search: ";if (find(vec, "first something")){std::cout << "success\n";}else{std::cout << "failure\n";}std::cout << "second search: ";if (find(vec, "second something")){std::cout << "success\n";}else{std::cout << "failure\n";}std::cout << "third search: ";if (!find(vec, "third something")){std::cout << "success (not found)\n";}else{std::cout << "failure\n";}}Σnigma   