ファンクターソリューションが大好きです:
template <int limit> class NegativeNumber
{
public:
NegativeNumber() : current(0) {};
int operator()()
{
return -(1 + (current++ % limit));
};
private:
int current;
};
次に、任意のジェネレーターを任意の制限で定義して使用できます。
NegativeNumber<5> five;
NegativeNumber<2> two;
for (int x = 0; x < 20; ++x)
std::cout << "limit five: " << five() << "\tlimit two: " << two() << '\n';
ジェネレーターをパラメーターとして別の関数に渡すこともできます。各ファンターには独自の状態があります。
void f5(NegativeNumber<5> &n)
{
std::cout << "limit five: " << n() << '\n';
}
void f2(NegativeNumber<2> &n)
{
std::cout << "limit two: " << n() << '\n';
}
f5(five);
f2(two);
制限を宣言するテンプレート ソリューションが気に入らない場合は、テンプレートなしのバージョンもあります。
class NegativeNumberNoTemplate
{
public:
NegativeNumberNoTemplate(int limit) : m_limit(limit), current(0) {};
int operator()()
{
return -(1 + (current++ % m_limit));
};
private:
const int m_limit;
int current;
};
関数の引数として使用することも同じように機能し、その内部状態も転送されます。
void f(NegativeNumberNoTemplate &n)
{
std::cout << "no template: " << n() << '\n';
}
NegativeNumberNoTemplate notemplate(3);
f(notemplate);
スレッドで使用したくないことを願っています。スレッドセーフではありません;)
ここにすべての例があります。それが役に立てば幸い。