Comparison is always false due to limited range ... with templates

c++, templates, warnings

Solution

#include <algorithm>

template<class T>
T& trim(T& val) {
  val = std::max(T(0), val);
  return val;
}

It's not apparent from the question that passing by non-const reference is appropriate. You can change the above return nothing (void), pass by value and return by value, or pass by const& and return by value:

template<class T>
T trim(T const& val);

// example use:
value = trim(value); // likely the most clear solution

Generalize a bit more, even though outside the scope of your question:

template<class T>
T constrain(T const& value, T const& lower, T const& upper) {
  // returns value if value within [lower, upper] (inclusive end points)
  // returns lower if value < lower
  // otherwise returns upper
  assert(lower <= upper); // precondition
  return std::min(std::max(value, lower), upper);
}

template<class T>
T constrain_range(T const& value, T const& lower, T const& upper) {
  // returns value if value within [lower, upper) (exclusive upper)
  // returns lower if value < lower
  // otherwise returns upper - 1
  assert(lower < upper); // precondition
  if      (value <  lower) return lower;
  else if (value >= upper) return upper - 1;
  else                     return value;
}

Problem

I have a templated function that operates on a template-type variable, and if the value is less than 0, sets it to 0. This works fine, but when my templated type is unsigned, I get a warning about how the comparison is always false. This obviously makes sense, but since its templated, I'd like it to be generic for all data types (signed and unsigned) and not issue the warning. I'm using g++ on Linux, and I'm guessing there's a way to suppress that particular warning via command line option to g++, but I'd still like to get the warning in other, non-templated, cases. I'm wondering if there's some way, in the code, to prevent this, without having to write multiple versions of the function? ``` template < class T > T trim(T &val) { if (val < 0) { val = 0; } return (val); } int main() { char cval = 5; unsigned char ucval = 5; cout << "Untrimmed: " << (int)cval; cval = trim(cval); cout << " Trimmed: " << (int)cval << endl; cout << "Untrimmed: " << (int)ucval; cval = trim(ucval); cout << " Trimmed: " << (int)ucval << endl; return (0); } ```

Original source