16 votes

Fonction STL permettant de vérifier si une valeur est comprise dans un certain intervalle ?

J'ai une fonction : bool inBounds(int value, int low, int high) . Existe-t-il un équivalent STL qui fasse des choses utiles (qui prenne des variables de différents types, en particulier) ? Je n'arrive pas à en trouver un en utilisant Google, et je préfère réutiliser plutôt que réécrire.

24voto

templatetypedef Points 129554

En C++17, il n'y a pas d'équivalent direct d'une telle fonction, mais pour les petits types avec des comparaisons d'égalité rapides, vous pouvez utiliser std::clamp :

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

Vous pouvez également écrire votre propre fonction pour tester cela :

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

Il s'agit de vérifier si value est compris dans l'intervalle [faible, élevé]. Si vous voulez l'intervalle [low, high], vous écrirez cela comme suit

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

Notez qu'elle est définie uniquement en termes de operator < ce qui signifie que toute classe qui ne supporte que les operator < peut être utilisé ici.

De même, en voici un qui utilise des comparateurs personnalisés :

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

Cette dernière a l'avantage de low y high ne doivent pas nécessairement être du même type que les value et tant que le comparateur peut gérer cela, il fonctionnera parfaitement.

J'espère que cela vous aidera !

6voto

molbdnilo Points 9289
bool inBounds(int value, int low, int high)

a le léger inconvénient de vous obliger à vous rappeler quel paramètre va où.
Je ne peux pas être le seul dont l'ordre parfaitement rationnel des paramètres est déconcertant lorsque l'on revient au code après un certain temps.

Vous pouvez aller plus loin et définir

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

Vous pouvez alors être plus explicite sur ce que vous voulez dire :

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

Si l'on est en mode abstraction, il n'est pas trop difficile de généraliser pour accommoder différentes combinaisons inclusives/exclusives.

Bien entendu, cela peut s'avérer excessif pour vos besoins.
YMMV, et tout le reste.

1voto

MSalters Points 74024

Vous pouvez en composer un à partir de std::less , std::more , std::bind y std::compose mais c'est vraiment exagéré.

Les lambdas sont beaucoup plus faciles à utiliser :

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

ou, si les valeurs basse et haute sont comprises dans le champ d'application

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

-2voto

bitemyapp Points 1388

Je pense qu'il serait préférable de ne pas tenter une tâche aussi triviale avec une fonction entière et de simplement intégrer le comportement.

Voici ce qu'il en est :

int main()
{
    int value = 5;
    int lower = 0;
    int upper = 10;

    bool inside = lower < value && value < upper;

    std::cout << "inside: " << inside;
}

Si vous avez une raison de ne pas écrire le code simplement de cette manière, veuillez m'en faire part et je pourrai vous fournir une réponse plus sophistiquée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X