An STL function to check if a value is in a range?

I have a function: bool inBounds(int value, int low, int high) . Is there an equivalent to STL that does useful things (in particular, it uses variables of different types)? I cannot find it using Google, and I would rather reuse than rewrite.

+4
source share
4 answers

In C ++ 14 there is no direct equivalent to such a function, but for smaller types with quick equality comparison you can use std::clamp :

 if (val == std::clamp(val, low, high)) { ... } 

Alternatively, you can simply write your own function to test for this:

 template <typename T> bool IsInBounds(const T& value, const T& low, const T& high) { return !(value < low) && (value < high); } 

This checks if value in the range [low, high). If you want a range of [low, high], you should write this as

 template <typename T> bool IsInBounds(const T& value, const T& low, const T& high) { return !(value < low) && !(high < value); } 

Notice how this is defined exclusively from the point of view of operator < , which means that any class that only supports operator < can be used here.

Similarly, a custom comparator is used here:

 template <typename T, typename R, typename Comparator> bool IsInBounds(const T& value, const R& low, const R& high, Comparator comp) { return !comp(value, low) && comp(value, high); } 

This last has a nice advantage: low and high should not be of the same type as value , and as long as the comparator can handle this, it will work fine.

Hope this helps!

+10
source
 bool inBounds(int value, int low, int high) 

has a slight flaw that you have to remember which parameter goes where.
I cannot be the only one whose impeccable ordering of the parameters is confusing when returning to the code after a while.

You can go the extra mile and determine

 template<typename T> class Interval { public: Interval(T lo, T hi) : low(lo), high(hi) {} bool contains(T value) const { return low <= value && value < high; } private: T low; T high; }; template<typename T> Interval<T> interval(T lo, T hi) { return Interval<T>(lo, hi); } 

Then you can more clearly indicate what you mean:

 if (interval(a, b).contains(value)) // ... 

If you are in abstraction mode, it is not too difficult to generalize to accommodate various inclusive / exclusive combinations.

Of course, this may be redundant for your purposes.
YMMV and all that.

+4
source

You can compile one of std::less , std::more , std::bind and std::compose , but this is really redundant.

Lambda is much simpler:

[](int value, int low, int high){return !(value < low) && (value < high);}

or if low and high in the field

[low, high](int value){return !(value < low) && (value < high)};

+1
source

I would almost think that you better not try to perform such an seemingly trivial task with an entire function and just embed the behavior.

Something like that:

  1 #include <iostream> 2 3 int main() { 4 int value = 5; 5 bool inside = false; 6 int lower = 0; 7 int upper = 10; 8 inside = lower < value && value < upper; 9 printf("inside: %d", inside); 10 return 0; 11 } 

If you have a reason not to write code just like that, please let me know and I can provide a more complex answer.

0
source

Source: https://habr.com/ru/post/1396125/


All Articles