Проблема с моим макросом зажима - PullRequest
2 голосов
/ 04 ноября 2010

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

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

Ответы [ 4 ]

15 голосов
/ 04 ноября 2010

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

template <typename T> T CLAMP(const T& value, const T& low, const T& high) 
{
  return value < low ? low : (value > high ? high : value); 
}
4 голосов
/ 04 ноября 2010

Ваш макрос в порядке. Если вы передадите 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);
}
1 голос
/ 04 ноября 2010

Использование шаблонной функции, как уже предлагалось, является лучшим решением.

В любом случае, если у вас проблемы такого рода (как с макросом, так и с функцией), вам следует упростить выражение; посмотрите на этот псевдокод:

max(a,b): a>b ? a : b
min(a,b): a<b ? a : b
clamp(x,lo,hi): min( hi, max(lo,x) )
0 голосов
/ 04 ноября 2010

Вы также можете сделать ее функцией inline, чтобы она была похожа на макрос, но безопаснее.

...