値が下限値を下回ったら、上限値を超えたら、という処理を以下のように書くことがよくありますが
// 下限 int a = 10; for (;;) // ループ条件はとりあえずなんでもいい { --a; if (a < 0) a = 0; }
// 上限 int a = 0; for (;;) { ++a; if (a > 10) a = 10; }
std::minとstd::maxを使うとスッキリ書けたりします。
// 下限 int a = 10; for (;;) { a = std::max(a - 1, 0); }
// 上限 int a = 0; for (;;) { a = std::min(a + 1, 10); }
でもこれだけだと、下限に達したとき、上限に達したときに何か処理をさせたい場合に不便なので
以下のように、minとmaxを拡張した関数を用意しておくと便利です。
ラムダ式がないとあまり便利と言えないので、ラムダ式がある前提で書きます。
// 下限 template <class T, class F> inline const T& lower_limit(const T& a, const T& b, F f) { return a > b ? a : ([&]() -> decltype((b)) { f(); return b; })(); } // 上限 template <class T, class F> inline const T& upper_limit(const T& a, const T& b, F f) { return a < b ? a : ([&]() -> decltype((b)) { f(); return b; })(); }
// 下限 int a = 10; bool b = true; while (b) { a = lower_limit(a - 1, 0, [&]{ b = false; }); // 下限に達したらループ終了 }
// 上限 int a = 0; bool b = true; while (b) { a = upper_limit(a + 1, 10, [&]{ b = false; }); // 上限に達したらループ終了 }
だから早くラムダ式ほしいです。せつじつなんです。
あ、でもstd::min/maxだけでも地味に便利ですよ。
追記:
id:DigitalGhostさんとどようびさんにご指摘いただいた点を修正したバージョン
template <class T, class F> inline const T& upper_limit(const T& a, const T& b, F f) { return a < b ? a : (static_cast<void>(f()), b); } template <class T, class F> inline const T& lower_limit(const T& a, const T& b, F f) { return a > b ? a : (static_cast<void>(f()), b); }
(f(), b)の括弧はいらないですが、(自分が)わかりやすいように付けてます。