staticと翻訳単位と乱数生成器

```/Users/yasuhisa/cpp% g++ -c bad1.cpp; g++ -c bad2.cpp; g++ bad1.o bad2.o bad_main.cpp; ./a.out
0.945805, 0.712418, 0.973565, 0.237499, 0.475996, 0.512646, 0.0423286, 0.418472, 0.975018, 0.120168,
0.573828, 0.0147206, 0.411715, 0.162769, 0.351549, 0.315692, 0.290796, 0.181917, 0.484411, 0.405733,
0.945805, 0.712418, 0.973565, 0.237499, 0.475996, 0.512646, 0.0423286, 0.418472, 0.975018, 0.120168,
```
```#ifndef BAD_RAND_HPP

#include <boost/random.hpp>

namespace math {
static boost::mt19937 gen_(static_cast<unsigned long>(time(NULL)));
static boost::uniform_real<> dst_(0, 1);
static boost::variate_generator<boost::mt19937, boost::uniform_real<> > rand_(gen_, dst_);
static boost::uniform_real<>::result_type random() {
return rand_();
};
};
#endif
```
```#ifndef BAD1_HPP

#include <vector>

void rand_vector1(std::vector<double>& v);

#endif
```
```#include "bad1.hpp"

void rand_vector1(std::vector<double>& v) {
for (int i = 0; i < 10; i++) {
v.push_back(math::random());
}
};
```
```#ifndef BAD2_HPP

#include <vector>

void rand_vector2(std::vector<double>& v);

#endif
```
```#include "bad2.hpp"

void rand_vector2(std::vector<double>& v) {
for (int i = 0; i < 10; i++) {
v.push_back(math::random());
}
};
```
```#include <iostream>
#include <boost/foreach.hpp>

int main(int argc, char *argv[]) {

std::vector<double> v;

rand_vector1(v);
BOOST_FOREACH(const double d, v) {
std::cout << d << ", ";
}
std::cout << std::endl;

v.clear();

rand_vector1(v);
BOOST_FOREACH(const double d, v) {
std::cout << d << ", ";
}
std::cout << std::endl;

v.clear();

rand_vector2(v);
BOOST_FOREACH(const double d, v) {
std::cout << d << ", ";
}
std::cout << std::endl;
v.clear();

return 0;
};
```

解決方法

```#ifndef BAD_RAND_HPP

#include <boost/random.hpp>

namespace math {
boost::uniform_real<>::result_type random();
};

#endif
```
```#include "bad_rand.hpp"

namespace math {
namespace {
boost::mt19937 gen_(static_cast<unsigned long>(time(NULL)));
boost::uniform_real<> dst_(0, 1);
boost::variate_generator<boost::mt19937, boost::uniform_real<> > rand_(gen_, dst_);
}
boost::uniform_real<>::result_type random() {
return rand_();
};
};
```

こうするとグローバルに一つ乱数生成器ができたことが分かる。

```/Users/yasuhisa/cpp% g++ -c bad_rand.cpp; g++ -c bad1.cpp; g++ -c bad2.cpp; g++ bad_rand.o bad1.o bad2.o bad_main.cpp; ./a.out
0.926492, 0.660651, 0.130457, 0.352934, 0.959027, 0.528594, 0.374438, 0.477017, 0.520979, 0.739577,
0.894449, 0.615949, 0.149972, 0.758141, 0.82672, 0.063639, 0.478917, 0.251075, 0.138039, 0.303442,
0.55342, 0.731289, 0.396713, 0.158482, 0.201625, 0.596329, 0.528284, 0.260341, 0.0301604, 0.200705,
```

あと、マルチスレッドとかを使うときには乱数生成器は状態を持っているので競合しては困る。ということでmutexのことを考えないといけない、というメモ。