std::generate and Function Adaptors

B

Bill Woessner

I'm trying to replace a loop with a call to std::generate and I'm
about at wits end. Here's the working code:

std::vector<double>::iterator it;
std::vector<double> data(100);
RandomGenerator<double> g;

for(it = data.begin(); it != data.end(); ++it)
{
*it = g.GetGaussian();
}

This works fine. So I thought I could use std::generate to accomplish
the same thing. I've tried lots of combinations, but this is the one
I thought most likely to work:

std::generate(data.begin(), data.end(),
std::bind1st(std::mem_fun(&RandomGenerator<double>::GetGaussian),
&g));

I thought this should work because GetGaussian effectively has one
parameter, namely the object it's being invoked on. However, when I
try to compile this, I get a slew of errors about first_argument_type
and second_argument_type not being defined.

Any thoughts?

Thanks in advance,
Bill
 
F

Fei Liu

Bill said:
I'm trying to replace a loop with a call to std::generate and I'm
about at wits end. Here's the working code:

std::vector<double>::iterator it;
std::vector<double> data(100);
RandomGenerator<double> g;

for(it = data.begin(); it != data.end(); ++it)
{
*it = g.GetGaussian();
}

This works fine. So I thought I could use std::generate to accomplish
the same thing. I've tried lots of combinations, but this is the one
I thought most likely to work:

std::generate(data.begin(), data.end(),
std::bind1st(std::mem_fun(&RandomGenerator<double>::GetGaussian),
&g));

I thought this should work because GetGaussian effectively has one
parameter, namely the object it's being invoked on. However, when I
try to compile this, I get a slew of errors about first_argument_type
and second_argument_type not being defined.

Any thoughts?

Thanks in advance,
Bill
because you don't need bind1st, try
std::generate(data.begin(), data.end(),
std::mem_fun(&RandomGenerator<double>::GetGaussian));
 
V

Victor Bazarov

Bill said:
I'm trying to replace a loop with a call to std::generate and I'm
about at wits end. Here's the working code:

std::vector<double>::iterator it;
std::vector<double> data(100);
RandomGenerator<double> g;

for(it = data.begin(); it != data.end(); ++it)
{
*it = g.GetGaussian();
}

This works fine. So I thought I could use std::generate to accomplish
the same thing. I've tried lots of combinations, but this is the one
I thought most likely to work:

std::generate(data.begin(), data.end(),
std::bind1st(std::mem_fun(&RandomGenerator<double>::GetGaussian),
&g));

I thought this should work because GetGaussian effectively has one
parameter, namely the object it's being invoked on. However, when I
try to compile this, I get a slew of errors about first_argument_type
and second_argument_type not being defined.

Any thoughts?

'binder1st' inherits from 'unary_function' accepting the second argument
of the function it binds. Since in your case the second argument doesn't
exist (it's 'void'), 'mem_fun' does not provide it, so it becomes missing
AFA 'binder1st' is concerned...

You would be better off using advanced binders from Boost, or providing
a simple operator() instead of 'GetGaussian' (or wrapping 'GetGaussian'
yourself).

template<class T> struct RandomGenerator {
T GetGaussian() const { return 42.; }
// other methods
};

template<class T> struct GaussianWrapper_t {
RandomGenerator<T> g;
GaussianWrapper_t(RandomGenerator<T> const& g) : g(g) {}
T operator()() const {
return g.GetGaussian();
}
};

template<class T>
GaussianWrapper_t<T> GaussianWrapper(RandomGenerator<T> const& g)
{
return GaussianWrapper_t<T>(g);
}

int main()
{
std::vector<double>::iterator it;
std::vector<double> data(100);
RandomGenerator<double> g;
std::generate(data.begin(), data.end(), GaussianWrapper(g));
}

V
 
V

Victor Bazarov

Fei said:
because you don't need bind1st, try
std::generate(data.begin(), data.end(),
std::mem_fun(&RandomGenerator<double>::GetGaussian));

How is 'generate' going to know what object to call it for?

V
 

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

Forum statistics

Threads
474,292
Messages
2,571,494
Members
48,174
Latest member
RonnyLoren

Latest Threads

Top