It’s actually superfluous for unsigned types, because you can just compare them directly to get the same result. In fact, internally all the isPositiveAndBelow does it cast it to an unsigned type and do exactly that!
…not really, if I want to check an int value, if it is positive and below a size_t, I still have to check both:
size_t upperLimit = std::numeric_limit<unsigned int>::max();
int valueToTest = -5;
In this case the check isPositiveAndBelow is not superfluous at all.
The implementation only works, because both arguments are of the same type. But I am talking of a very common use-case, that the second argument is coming from an unsigned int (any std::size() method).
In this case it would need to be:
template <>
inline bool isPositiveAndBelow (const int valueToTest, const unsigned int upperLimit) noexcept
{
jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
return valueToTest >= 0 && static_cast<unsigned int> (valueToTest) < static_cast<unsigned int> (upperLimit);
}