Функция STL для проверки, находится ли значение в некотором диапазоне? - PullRequest
8 голосов
/ 13 февраля 2012

У меня есть функция: bool inBounds(int value, int low, int high). Есть ли в STL-эквиваленте полезные вещи (в частности, переменные разных типов)? Я не могу найти один с помощью Google, и я предпочел бы повторно использовать, а не переписывать.

Ответы [ 4 ]

11 голосов
/ 13 февраля 2012

В C ++ 14 нет прямого эквивалента такой функции, но для небольших типов с быстрым сравнением на равенство вы можете использовать std::clamp:

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

В качестве альтернативы, вы можете просто написать свою собственную функцию для проверки:

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

Проверяет, находится ли value в диапазоне [низкий, высокий). Если вы хотите диапазон [низкий, высокий], вы должны написать это как

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

Обратите внимание, что это определяется исключительно в терминах operator <, что означает, что здесь может использоваться любой класс, который поддерживает только operator <.

Аналогично, вот один с использованием пользовательских компараторов:

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);
}

У этого последнего есть приятное преимущество в том, что low и high не обязательно должны быть того же типа, что и value, и до тех пор, пока компаратор может справиться, он будет работать просто отлично.

Надеюсь, это поможет!

5 голосов
/ 13 февраля 2012
bool inBounds(int value, int low, int high)

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

Вы можете пройти лишнюю милю и определить

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); }

Тогда вы сможете более точно понять, что вы имеете в виду:

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

Если кто-то находится в режиме абстракции, это не так уж сложнообобщите, чтобы учесть различные комбинации «включительно / эксклюзивно».

Конечно, это может быть излишним для ваших целей.
YMMV, и все такое.

1 голос
/ 13 февраля 2012

Вы можете составить один из std::less, std::more, std::bind и std::compose, но это действительно излишне.

Лямбда гораздо проще:

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

или, если низкий и высокий находятся в области действия

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

0 голосов
/ 13 февраля 2012

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

Примерно так:

  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 }

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...