views:

214

answers:

1

I am trying to remove short strings from a vector.

std::vector<std::string> vec;

// ...

vec.erase(std::remove_if(vec.begin(),
                         vec.end(),
                         boost::bind(std::less<size_t>(),
                                     boost::bind(&std::string::length, _1),
                                     5),
          vec.end());

The compiler spits out a very large error message:

qwer.cpp:20: error: no matching function for call to 'remove_if(__gnu_cxx::__nor
mal_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char
> >*, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator
<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::al
locator<char> > > > >, __gnu_cxx::__normal_iterator<std::basic_string<char, std:
:char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char,
 std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_strin
g<char, std::char_traits<char>, std::allocator<char> > > > >, boost::_bi::bind_t
<boost::_bi::unspecified, std::less<unsigned int>, boost::_bi::list2<boost::_bi:
:bind_t<unsigned int, boost::_mfi::cmf0<unsigned int, std::basic_string<char, st
d::char_traits<char>, std::allocator<char> > >, boost::_bi::list1<boost::arg<1>
> >, boost::_bi::value<int> > >, __gnu_cxx::__normal_iterator<std::basic_string<
char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_st
ring<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::b
asic_string<char, std::char_traits<char>, std::allocator<char> > > > >)'

The following solution works:

vec.erase(std::remove_if(vec.begin(),
                         vec.end(),
                         boost::bind(&std::string::length, _1) < 5),
          vec.end());

But I am still curious as to what I did wrong in the first version. Thanks!

+5  A: 

It looks like you got your parenthesis off (there should be two after 5, one to close the bind, one to close the remove_if.) I am surprised this didn't give another error message about invalid token or something though, as the parens are clearly unbalanced (did you remove an extra close paren from the end while preparing for SO?). It looks like this is the case, because if you read the template arguments to remove_if in the error message, the next to last one is a boost bind_t, followed by another gnu::iterator.

Todd Gardner
Lol thanks, that was a stupid mistake.
FredOverflow
Um, so it compiles now? Still looks off to me.. and I don't even know why your second "solution" even compiles.
Terry Mahaffey
Bind overloads some operators to make writing predicates faster. It is a very neat feature: http://www.boost.org/doc/libs/1_41_0/libs/bind/bind.html#operators
Todd Gardner
whoa. std::bind does not do that.
Terry Mahaffey
boost still rocks C++0x on a few counts… things will get confusing.
Potatoswatter
looks like tr1 bind doesn't even support nested bind statements correctly (or at least the VC implementation of tr1 bind). I thought they were a lot closer than they actually are..
Terry Mahaffey
You actually managed to extract some info from that error message? I'm extremely impressed - it all turned into a mishmosh of `< <` , `std::` and `> >` for me after the first line.
kibibu