Предупреждение для любого, кто пытается сделать что-то подобное, где вы ограничиваете возможные значения типа ввода.
template<typename T>
T clamp(T input)
{
return boost::algorithm::clamp(input,
std::numeric_limits<T>::min(),
std::numeric_limits<T>::max());
}
Это не удастся для некоторых значений T
и input
.Например:
clamp<int16_t>(32768.0);
вернет
-32767
Попробуйте и посмотрите.Проблема в том, что input
приводится к T
при входе в функцию, прежде чем будут сделаны сравнения.И если вы static_cast<int16_t>(+32768)
, вы получите UB.
У меня нет хорошего решения, кроме приведенного ниже кода, который «лучше», но не завершен.Это работает для небольших целочисленных типов (int16_t
и int32_t
) и одинарной точности float
, но имеет проблемы с int64_t
и double
.
template<typename T>
T clamp(double input)
{
double intermediate = return boost::algorithm::clamp<double>(input,
std::numeric_limits<T>::min(),
std::numeric_limits<T>::max());
return boost::numeric_cast<T>(intermediate);
}