I am using the following struct as an input to STL's generate_n
algorithm:
struct GenerateNumber {
GenerateNumber () : i(0) {}
int operator () (void) {
return i++;
}
private:
int i;
};
An example to the code that uses this functor is:
std::vector <int> v1 (3);
std::vector <int> v2 (3);
GenerateNumber generateNumber;
std::generate_n (v1.begin (), 3, generateNumber);
std::generate_n (v2.begin (), 3, generateNumber);
However, the result is that both v1
and v2
contain {0,1,2}
, instead of v2
to contain {3,4,5}
. I have verified with a breakpoint that the GenerateNumber
's constructor is called only once (I know it doesn't make sense that the constructor is called more then once, but I checked it anyway).
I know I can solve this by making i
static, but I don't understand this behavior. How come the value of i
is not kept between consecutive calls?
The generator object is copied when passed to generate_n
. Try using std::ref
, i.e.
std::generate_n(v1.begin(), 3, std::ref(generateNumber));
std::generate_n(v2.begin(), 3, std::ref(generateNumber));
Edit: Note that std::ref
is only available in C++11. It was introduced in TR1 as std::tr1::ref
, and is also available in boost as boost::ref
.
std::generate_n takes the functor by value, that is, it makes a copy of it. It could be that you didn't check that the copy constructor was being called.
In the absence of std::ref
, and if your problem is localised as in your example, you could modify your functor to take a reference to a counter set in the scope of the calls to std::generate_n
:
struct GenerateNumber {
GenerateNumber (int& i) : struct GenerateNumber {
GenerateNumber () : i(0) {}
int operator () (void) {
return i++;
}
private:
int& i;
};
int main() {
int counter = 0;
std::vector <int> v1 (3);
std::vector <int> v2 (3);
GenerateNumber generateNumber(counter);
std::generate_n (v1.begin (), 3, generateNumber);
std::generate_n (v2.begin (), 3, generateNumber);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With