Namespaces
Variants

std::ranges::ends_with

De fr.cppreference.net
 
 
Bibliothèque des algorithmes
Algorithmes contraints et algorithmes sur les plages (C++20)
Algorithmes contraints, p. ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Opérations de tri et connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur des plages partitionnées)
Opérations d'ensemble (sur des plages triées)
Opérations de fusion (sur des plages triées)
Opérations de tas
Opérations de minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations de séquence non modificatrices
Opérations de séquence modificatrices
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur des plages triées)
       
       
Opérations d'ensemble (sur des plages triées)
Opérations de tas
Opérations de minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
Défini dans l'en-tête <algorithm>
Signature d'appel
template< std::input_iterator I1, std::sentinel_for<I1> S1,
          std::input_iterator I2, std::sentinel_for<I2> S2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
requires (std::forward_iterator<I1> || std::sized_sentinel_for<S1, I1>) &&
         (std::forward_iterator<I2> || std::sized_sentinel_for<S2, I2>) &&
         std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr bool ends_with( I1 first1, S1 last1,
                          I2 first2, S2 last2, Pred pred = {},
                          Proj1 proj1 = {}, Proj2 proj2 = {} );
(1) (depuis C++23)
template< ranges::input_range R1, ranges::input_range R2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
requires (ranges::forward_range<R1> || ranges::sized_range<R1>) &&
         (ranges::forward_range<R2> || ranges::sized_range<R2>) &&
         std::indirectly_comparable<ranges::iterator_t<R1>,
                                    ranges::iterator_t<R2>,
                                    Pred, Proj1, Proj2>
constexpr bool ends_with( R1&& r1, R2&& r2, Pred pred = {},
                          Proj1 proj1 = {}, Proj2 proj2 = {} );
(2) (depuis C++23)

Vérifie si la deuxième plage correspond au suffixe de la première plage.

1) Soit N1 = ranges::distance(first1, last1) et N2 = ranges::distance(first2, last2):
  • Si N1 < N2 est true, renvoie false.
  • Sinon, renvoie ranges::equal(std::move(first1) + (N1 - N2), last1,
    std::move(first2), last2, pred, proj1, proj2)
    .
2) Soit N1 = ranges::distance(r1) et N2 = ranges::distance(r2).
  • Si N1 < N2 est true, renvoie false.
  • Sinon, renvoie ranges::equal(views::drop(ranges::ref_view(r1),
    N1 - static_cast<decltype(N1)>(N2)),
    r2, pred, proj1, proj2)
    .

Les entités de type fonction décrites sur cette page sont des objets fonctions d'algorithmes (informellement appelés niebloids), c'est-à-dire :

Paramètres

first1, last1 - la paire itérateur-sentinelle définissant la plage d'éléments à examiner
r1 - la plage d'éléments à examiner
first2, last2 - la paire itérateur-sentinelle définissant la plage d'éléments à utiliser comme suffixe
r2 - la plage d'éléments à utiliser comme suffixe
pred - le prédicat binaire qui compare les éléments projetés
proj1 - la projection à appliquer aux éléments de la plage à examiner
proj2 - la projection à appliquer aux éléments de la plage à utiliser comme suffixe

Valeur de retour

true si la deuxième plage correspond au suffixe de la première plage, false sinon.

Complexité

Généralement linéaire : au plus min(N1,N2) applications du prédicat et des deux projections. Le prédicat et les deux projections ne sont pas appliqués si N1 < N2 est true.

Si à la fois N1 et N2 peuvent être calculés en temps constant (c'est-à-dire que les deux paires de types itérateur-sentinelle modélisent sized_sentinel_for, ou que les deux types de plages modélisent sized_range) et que N1 < N2 est true, la complexité temporelle est constante.

Implémentation possible

struct ends_with_fn
{
    template<std::input_iterator I1, std::sentinel_for<I1> S1,
             std::input_iterator I2, std::sentinel_for<I2> S2,
             class Pred = ranges::equal_to,
             class Proj1 = std::identity, class Proj2 = std::identity>
    requires (std::forward_iterator<I1> || std::sized_sentinel_for<S1, I1>) &&
             (std::forward_iterator<I2> || std::sized_sentinel_for<S2, I2>) &&
             std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
    constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2,
                              Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        const auto n1 = ranges::distance(first1, last1);
        const auto n2 = ranges::distance(first2, last2);
        if (n1 < n2)
            return false;
        ranges::advance(first1, n1 - n2);
        return ranges::equal(std::move(first1), last1,
                             std::move(first2), last2,
                             pred, proj1, proj2);
    }
    
    template<ranges::input_range R1, ranges::input_range R2,
             class Pred = ranges::equal_to,
             class Proj1 = std::identity, class Proj2 = std::identity>
    requires (ranges::forward_range<R1> || ranges::sized_range<R1>) &&
             (ranges::forward_range<R2> || ranges::sized_range<R2>) &&
             std::indirectly_comparable<ranges::iterator_t<R1>,
                                        ranges::iterator_t<R2>,
                                        Pred, Proj1, Proj2>
    constexpr bool operator()(R1&& r1, R2&& r2,
                              Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        const auto n1 = ranges::distance(r1);
        const auto n2 = ranges::distance(r2);
        if (n1 < n2)
            return false;
        return ranges::equal(views::drop(ranges::ref_view(r1),
                                         n1 - static_cast<decltype(n1)>(n2)),
                             r2, pred, proj1, proj2);
    }
};

inline constexpr ends_with_fn ends_with{};

Notes

Macro de test de fonctionnalités Valeur Std Fonctionnalité
__cpp_lib_ranges_starts_ends_with 202106L (C++23) std::ranges::starts_with, std::ranges::ends_with

Exemple

#include <algorithm>
#include <array>

static_assert
(
    ! std::ranges::ends_with("for", "cast") &&
    std::ranges::ends_with("dynamic_cast", "cast") &&
    ! std::ranges::ends_with("as_const", "cast") &&
    std::ranges::ends_with("bit_cast", "cast") &&
    ! std::ranges::ends_with("to_underlying", "cast") &&
    std::ranges::ends_with(std::array{1, 2, 3, 4}, std::array{3, 4}) &&
    ! std::ranges::ends_with(std::array{1, 2, 3, 4}, std::array{4, 5})
);

int main() {}

Rapports de défauts

Les rapports de défauts suivants, modifiant le comportement, ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement tel que publié Comportement correct
LWG 4105 C++23 la surcharge (2) calculait la différence
de taille par N1 - N2[1]
changé en
N1 - static_cast<decltype(N1)>(N2)
  1. Son résultat pourrait être d'un type de classe entier, dans ce cas ranges::drop_view ne peut pas être construit.

Voir aussi

vérifie si une plage commence par une autre plage
(objet fonction d'algorithme)
(C++20)
vérifie si la chaîne se termine par le suffixe donné
(fonction membre publique de std::basic_string<CharT,Traits,Allocator>)
(C++20)
vérifie si la vue chaîne se termine par le suffixe donné
(fonction membre publique de std::basic_string_view<CharT,Traits>)