I have a very simple class, which has an x, y and z values. Like so:
class Individual
{
public:
static std::unique_ptr<Individual> Spawn(std::mt19937& rng);
Individual(double x, double y)
:
x(x),
y(y)
{
SetZ();
}
double GetZ() const
{
return z;
}
private:
void SetZ()
{
z = x * 0.123f y * 0.912f;
}
private:
double x = 0.0f;
double y = 0.0f;
double z = 0.0f;
};
The Spawn method just generates random values for x and y and spawns an individual:
std::unique_ptr<Individual> Individual::Spawn(std::mt19937& rng)
{
std::uniform_real_distribution<double> dist(-10.0f, 10.0f);
return std::make_unique<Individual>(dist(rng), dist(rng));
}
The problem is that in main.cpp I've got a vector of these individuals, and I'm trying to populate it with 10 random individuals via std::generate_n :
std::mt19937 rng = std::mt19937(std::random_device{}());
std::vector<std::unique_ptr<Individual>> individuals;
std::generate_n(individuals.begin(), 10,
Individual::Spawn(rng));
However I'm getting an error: error C2064: term does not evaluate to a function taking 0 arguments.
What gives? What am i doing wrong? Any help/criticism is appreciated
CodePudding user response:
generate_n
's last argument is meant to be a function, not a value. That function will be called n
times, once for each element to generate. You are giving it a std::unique_ptr
. Wrap your Spawn(rng)
call in a lambda expression instead.
Additionally, std::generate_n
requires an iterator to the start of a range that is at least n
elements in size. It does not (it can't) use that iterator to insert new elements, non-member algorithms can never do that with an iterator. One solution is to wrap the container with std::back_inserter
to create an output iterator that will extend the container as needed. Alternatively, you can resize
the vector to a size of 10 before calling generate_n
.
Acorrect implementation for your function is :
std::mt19937 rng = std::mt19937(std::random_device{}());
std::vector<std::unique_ptr<Individual>> individuals;
std::generate_n(
std::back_inserter(individuals),
10,
[&rng](){ return Individual::Spawn(rng); });
Live demo : https://godbolt.org/z/756Ejscvd