Jump to content
  • Advertisement
Sign in to follow this  
Toni Petrina

How to to this via C++ std and/or boost [SOLVED]

This topic is 4583 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, let's say we have a complex structure such as
struct something
{
  std::string strName;
  //...irrelevant
};
Is it possible to do something like this for std::*_if family if functions
std::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]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Toni Petrina
Ok, let's say we have a complex structure such as

struct something
{
std::string strName;
//...irrelevant
};


Is it possible to do something like this for std::*_if family if functions

std::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...]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Quote:
Original post by Toni Petrina
I know how to write my own predicate...
Oops, sorry about that :-| Guess I didn't read the question very well...

Share this post


Link to post
Share on other sites
From the boost::lambda library's documentation

Quote:
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.

Share this post


Link to post
Share on other sites
EDIT:
Actually, it doesn't work.
I tried something like this although it is broken

struct 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 iterator
something *s = boost::bind(d, refIterator)();
// then get member
_CompareType &c = s->*m;
// finally compare
return _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]

Share this post


Link to post
Share on other sites
Finally, solution is

namespace 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 this

std::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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!