クランプマクロに問題があります。値が10を超え、高さが17を超えると、機能しなくなります。何か案が?
#define CLAMP(value, low, high) (((value)<(low))?(low):(((value)>(high))?(high):(value)))
I would suggest using a safer way than a macro:
template <typename T> T CLAMP(const T& value, const T& low, const T& high)
{
return value < low ? low : (value > high ? high : value);
}
マクロは問題ありません。high
未満のを渡すと、low
奇妙な結果が表示されますが、それが原因である可能性は低いです。
++
最も可能性の高い結果は、演算子の使用や関数の呼び出しなどの副作用がある式を渡した場合です。副作用のある式がある場合、マクロ置換の仕組みにより、副作用が複数回発生する可能性があります。例えば:
CLAMP(x++, low, high) // expands to:
(x++ < low) ? low : ((x++ > high) ? high : x++);
x++
は複数回評価されますが、これは間違いなくあなたが望むものではありません(シーケンスポイントがないため、未定義の動作です)。
マクロをテンプレートとして書き直すことをお勧めします。
template <typename T> T CLAMP(T value, T low, T high)
{
return (value < low) ? low : ((value > high) ? high : value);
}
すでに提案されているようにテンプレート関数を使用することは、より良い解決策です。
とにかく、この種の問題 (マクロまたは関数の両方) がある場合は、式を単純化する必要があります。この擬似コードを見てください:
max(a,b): a>b ? a : b
min(a,b): a<b ? a : b
clamp(x,lo,hi): min( hi, max(lo,x) )
inline
マクロのようになりますが、より安全になるように関数にすることもできます。