Chaining std::accumulate and std::transform into a one-liner using boost::bind?

T

Tom Lynch

Hey all,

I've been messing around trying to turn a std::transform to an
intermediate vector followed by a std::accumulate into a single
application of std::accumulate with a binary functor built "on the
fly" using Boost Bind.

Unfortunately, my best guess as to how to use the "nested" binds that
are required (specifying the placeholders of the main bind inside the
inner binds seems to be incorrect.

Be interested to hear any suggestions as to why this is or is not
possible, or a good idea :)

Tom

----------------------------

#include <boost/bind.hpp>
#include <functional>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <vector>
#include <string>

using namespace std;
using bind;

struct StringReverser
{
StringReverser(const char* input): contents_(input) {}
string getReverse()
{
string result(contents_);
reverse(result.begin(), result.end());
return result;
}
string contents_;
};

int main()
{
vector<StringReverser> inputs;

// ... populate with whatever
const char* NAMES[] = {"Bob", "Larry", "David"};
inputs.assign(NAMES, NAMES + 3);

// transform, then accumulate: works
string acc;
vector<string> capitalised;

transform(inputs.begin(), inputs.end(), back_inserter(capitalised),
bind(&StringReverser::reverse, _1));
cout << accumulate(capitalised.begin(), capitalised.end(), acc,
plus<string>()) << endl;
// output is "boByrraLdivaD" as expected

// attempted one-liner: doesn't work
/*StringReverser base("");
cout << accumulate(inputs.begin(), inputs.end(), base,
bind(plus<string>(),
bind(&StringReverser::reverse, _1),
bind(&StringReverser::reverse, _2))) << endl;*/
return 0;
}
 
M

Michael DOUBEZ

Tom Lynch a écrit :
Hey all,

I've been messing around trying to turn a std::transform to an
intermediate vector followed by a std::accumulate into a single
application of std::accumulate with a binary functor built "on the
fly" using Boost Bind.

Unfortunately, my best guess as to how to use the "nested" binds that
are required (specifying the placeholders of the main bind inside the
inner binds seems to be incorrect.
[snip]

cout << accumulate(inputs.begin(), inputs.end(), base,
bind(plus<string>(),
bind(&StringReverser::reverse, _1),
bind(&StringReverser::reverse, _2))) << endl;*/


Yes your usage of place holder is wrong: a _n placeholder argument means
"substitute with the nth input argument."
Supposing StringReverser::reverse take only one argument (you didn't
provide it):
bind(&StringReverser::reverse,_1) should be good.

I suppose the double string reverse is not wat you want. Your
accumulation would expand to a loop performing:
base = StringReverser::reverse(base) + StringReverser::reverse(*it)
So it should be something like:
bind(plus<string>(),_1,bind(&StringReverser::reverse_1));

NOTE: if you want to accumulate reversed string an easier way is to use
a reverse_iterator and a single reverse:
StringReverser::reverse(accumulate(inputs.rbegin(),inputs.rend(),string()));

Michael
 
T

Tom Lynch

I suppose the double string reverse is not wat you want. Your
accumulation would expand to a loop performing:
base = StringReverser::reverse(base) + StringReverser::reverse(*it)
So it should be something like:
bind(plus<string>(),_1,bind(&StringReverser::reverse_1));

Yep. I later discovered that was what I needed.
NOTE: if you want to accumulate reversed string an easier way is to use
a reverse_iterator and a single reverse:
StringReverser::reverse(accumulate(inputs.rbegin(),inputs.rend(),string()));

Yeah, there are definitely better ways to solve that particular
problem, however it was one I contrived for the purposes of the post.

Thanks for your advice.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top