I was wandering how it's possible to reverese string
s that are contained in a vector
using a single for_each
command just in one "simple" line.
Yea, I know it is easy with a custom functor, but I can't accept, that it can't be done using bind
(at least I couldn't do it).
#include <vector>
#include <string>
#include <algorithm>
std::vector<std::string> v;
v.push_back("abc");
v.push_back("12345");
std::for_each(v.begin(), v.end(), /*call std::reverse for each element*/);
Edit: Thanks a lot for those funtastic solutions. However, the solution for me was not to use the tr1::bind that comes with the Visual Studio 2008 feature pack/SP1. I don't know why it does not work like expected but that's the way it is (even MS admits that it's buggy). Maybe some hotfixes will help.
With boost::bind everything works like desired and is so easy (but sometimes relly messy:)). I really should have tried boost::bind in the first place...
std::for_each expects a unary function (or at least something with the typedefs of a unary function).
std::reverse<> is a binary function. It takes two iterators. It would be possible to bind it all together using boost::bind, but it would be a pretty horrible mess. Something like:
boost::bind(
&std::reverse<std::string::iterator>,
boost::bind(&std::string::begin, _1),
boost::bind(&std::string::end, _1))
Better, I think, would be to write a reusable function called reverse_range like so:
template <class Range>
void reverse_range(Range& range)
{
std::reverse(range.begin(), range.end());
}
(probably with some metaprogramming to ensure that Range& isn't a double-reference)
And then use that in your for_each (after adapting it to be a unary function, of course).
std::for_each(v.begin(), v.end(),
std::ptr_fun(&reverse_range<std::string>));
EDIT:
Because string::begin and string::end have both const and non-const variants, it is necessary to cast them (as litb discovered while I was off writing them to test my answer ... +1!). This makes it very verbose. Typedefs can make it a bit more sanitary, but to stick with the one-liner theme:
boost::bind(
&std::reverse<std::string::iterator>,
boost::bind(
(std::string::iterator (std::string::*)())&std::string::begin, _1),
boost::bind(
(std::string::iterator (std::string::*)())&std::string::end, _1)
)
);
Which just screams for refactoring.
Finally, because I'm bored, bonus points for C++0x:
std::for_each(v.begin(), v.end() [](std::string& s){ std::reverse(s); });
EDIT: boost::bind works just fine, no need for boost::lambda.