Проблема с моим макросом зажима

У меня проблема с моим макросом зажима, когда, когда мое значение превышает 10, а мой максимум превышает 17, оно перестает работать. Любая идея?

#define CLAMP(value, low, high) (((value)<(low))?(low):(((value)>(high))?(high):(value)))

4 ответа

Решение

Я бы предложил использовать более безопасный способ, чем макрос:

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 функция, так что это будет как макрос, но безопаснее.

Другие вопросы по тегам