Partager via


Adaptateurs de plage

Les adaptateurs de plage créent une vue (une des classes View dans l’espace std::views de noms) à partir d’une plage. Nous vous recommandons d’utiliser un adaptateur pour créer des vues au lieu de créer directement les types d’affichages. Les adaptateurs sont le moyen prévu d’accéder aux vues. Ils sont plus faciles à utiliser, et dans certains cas plus efficaces, que la création d’instances des types d’affichage directement.

Une vue est un objet léger qui fait référence à des éléments d’une plage. Une vue peut :

  • Se compose uniquement de certains éléments d’une plage.
  • Représente une transformation d’éléments à partir d’une plage.
  • Il s’agit de l’inverse ou uniquement des premiers n éléments d’une plage.
  • Il s’agit d’une combinaison des éléments précédents.

Une vue est bon marché, O(1), pour copier, affecter et détruire- peu importe le nombre d’éléments impliqués. Prenons l’exemple suivant :

// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> input =  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto divisible_by_three = [](const int n) {return n % 3 == 0;};
    auto square = [](const int n) {return n * n;};

    auto x = input | std::views::filter(divisible_by_three)
                   | std::views::transform(square);

    for (int i : x)
    {
        std::cout << i << ' ';
    }
}
0 9 36 81

Le premier adaptateur de plage, filterfournit une vue qui contient les éléments de input ce qui sont divisibles par trois. L’autre adaptateur de plage, transformprend la vue qui contient les éléments divisent par trois et fournit une vue du carré de ces éléments.

Lorsqu’un adaptateur de plage produit une vue, il n’entraîne pas le coût de transformation de chaque élément de la plage pour produire cette vue. Le coût de traitement d’un élément dans la vue est payé uniquement lorsque vous accédez à cet élément.

La création d’une vue consiste à préparer le travail à l’avenir. Dans l’exemple précédent, la création de la vue n’entraîne pas la recherche de tous les éléments divisibles par trois ou laquament de ces éléments. Le travail se produit uniquement lorsque vous accédez à un élément dans la vue.

Les éléments d’une vue sont généralement les éléments réels de la plage utilisée pour créer la vue. La vue ne possède généralement pas les éléments ; elle leur fait simplement référence, à l’exception de owning_view. La modification d’un élément change cet élément dans la plage à partir de laquelle la vue a été créée. L’exemple suivant montre ce comportement :

#include <algorithm>
#include <iostream>
#include <ranges>

int main()
{
    int input[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto even = [](const int n) { return n % 2 == 0; };
    auto x = input | std::views::filter(even); // create a view of the even elements from input

    for (int &i : x)
    {
        std::cout << i << ' '; // 0 2 4 6 8 10
    }
    std::cout << '\n'; 

    std::ranges::fill(x, 42); // changes the evens from input[] to 42
    for (int &i : input) // demonstrates that the even elements in the range are modified
    {
        std::cout << i << ' '; // // 42 1 42 3 42 5 42 7 42 9 42
    }
}

Les adaptateurs de plage sont fournis sous de nombreuses formes. Par exemple, il existe des adaptateurs de plage qui vous permettent de produire une vue par :

  • Filtrage d’une autre plage en fonction d’un prédicat (filter).
  • Transformation des éléments dans une plage (transform).
  • Fractionnement d’une plage (split).

Les adaptateurs de plage peuvent être chaînés (composés). C’est là que la puissance et la flexibilité des plages sont les plus apparentes. La composition d’adaptateurs de plage vous permet de surmonter un problème principal avec les algorithmes STL (Standard Template Library) précédents, c’est-à-dire qu’ils ne sont pas faciles à chaîner ensemble.

Les adaptateurs de plage suivants sont disponibles dans l’espace std::views de noms. L’espace std::views de noms est un alias pratique pour std::ranges::views.

Adaptateur de plage Description
allC++20 Créez une vue qui fait référence à une plage et à ses éléments.
commonC++20 Créez une vue qui a le même itérateur et les mêmes types sentinelles à partir d’une plage qui ne le fait pas.
countedC++20 Créez une vue des n premiers éléments d’une plage, à partir de l’emplacement spécifié.
dropC++20 Créez une vue à partir d’une autre vue, en ignorant le nombre spécifié d’éléments à partir de l’avant.
drop_whileC++20 Créez une vue qui contient les éléments d’une plage qui restent après les éléments de début qui correspondent à la condition spécifiée sont supprimés.
elementsC++20 Créez une vue de l’index sélectionné dans chaque valeur de type tuple dans une plage.
emptyC++20 Créez une vue qui n’a aucun élément.
filterC++20 Créez une vue qui contient les éléments d’une plage qui correspondent à la condition spécifiée.
iotaC++20 Créez une vue qui contient une séquence de valeurs croissantes.
istreamC++20 Créez une vue sur les éléments d’un flux.
joinC++20 Créez une vue qui combine tous les éléments de plusieurs plages en une seule vue.
keysC++20 Créez une vue du premier index dans chaque valeur de type tuple dans une collection.
lazy_splitC++20 Fractionnez une vue en sous-plages en fonction d’un délimiteur.
reverseC++20 Créez une vue des éléments d’une plage dans l’ordre inverse.
singleC++20 Créez une vue qui contient un élément.
splitC++20 Fractionnez une vue en sous-plages en fonction d’un délimiteur.
takeC++20 Créez une vue des premiers n éléments d’une autre vue.
take_whileC++20 Créez une vue qui contient les éléments principaux d’une plage qui correspondent à la condition spécifiée.
transformC++20 Créez une vue des éléments transformés à partir d’une autre vue.
valuesC++20 Créez une vue du deuxième index dans chaque valeur de type tuple dans une collection.

Dans le tableau précédent, un adaptateur de plage est généralement décrit comme prenant une plage et produisant une vue. Pour être précis, les adaptateurs de plage ont un argument de plage qui accepte l’une des options suivantes :

  • Les cv-unqualified modèles viewde type et l’argument est une valeur rvalue ou peut être copié.
  • Lorsque vous passez l’argument en tant que lvalue, il doit modéliser range et vivre tant que la vue.
  • Lorsque vous passez l’argument en tant que rvalue, par exemple lors de l’appel owning_view, il doit modéliser range et movable.

Les fonctions d’adaptateur de plage sont généralement des objets de fonction, qui ressemblent à des appels de fonction et appliquent des contraintes sur les types qui peuvent être passés.

Vous pouvez passer des adaptateurs de plage et le résultat des opérations de canal (|) au code qui attend des objets de fonction. Dans l’exemple suivant, la vue créée par l’adaptateur split de plage est passée à l’adaptateur transform de plage comme si par un appel de fonction, car l’adaptateur transform de plage est un objet de fonction.

std::map<int, string> x = {{0, "Hello, world"}, {42, "Goodbye, world"}};
auto y = x | views::values | views::transform(views::split(' '));
// y is a range whose elements are ranges of whitespace-delimited strings from each value in x:
// {{"Hello", "world"}, {"Goodbye", "world"}}

all

Créez une vue de tous les éléments d’une plage.

template <ranges::viewable_range R>
constexpr ranges::view auto all(R&& rg) const noexcept;

Paramètres

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

Valeur retournée

  • S’il rg s’agit déjà d’une vue, une copie de rg.
  • S’il s’agit rg d’une valeur lvalue non-view, qui ref_view fait référence à rg. (La durée de vie de la vue est liée à la durée de vie de rg.)
  • S’il rg s’agit d’une valeur rvalue non-view telle qu’un objet temporaire ou est le résultat de la transmission de la plage à std::move, un owning_view.

Permet std::views::all_t<decltype((rg))> d’obtenir le type de la vue retournée.

Notes

Cet adaptateur de plage est le meilleur moyen de convertir une plage en vue. Une raison pour créer une vue à partir d’une plage consiste à la passer par valeur à faible coût, si le passage de la plage par valeur peut être coûteux.

L’obtention d’une vue pour une plage est une alternative utile à la transmission d’une plage lourde par valeur, car les vues sont peu coûteuses pour créer, copier et détruire. Une exception possible est owning_view, qui est une vue propriétaire de la plage sous-jacente.

En général, le pire scénario de destruction d’une vue présente O(N) une complexité pour le nombre d’éléments de la plage. Même si vous détruisez K des copies d’affichage avec N des éléments, la complexité totale est toujours O(N) parce que la plage sous-jacente n’est détruite qu’une seule fois.

Exemple : all

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
    auto myRefView = std::views::all(v); // create a ref_view of the vector
    std::cout << myRefView.size() << '\n'; // 10

    auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
    std::cout << myRefView.size() << '\n'; // outputs 0 because myOwningView now owns the elements
    std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
    std::cout << myOwningView.size(); // 10 
}
10
0
0
10

common

Créez une vue qui a le même type d’itérateur de début et de sentinelle à partir d’une plage qui risque de ne pas le faire.

template <ranges::viewable_range R>
constexpr ranges::view auto common(R&& rg) const noexcept;

Paramètres

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

Valeur retournée

  • views::all(rg) s’il s’agit rg d’une plage avec le même itérateur et le même type de sentinelle.
  • common_view(views::all(rg)) s’il rg existe différents types d’itérateurs et de sentinelles.

Notes

Lorsqu’une API nécessite que l’itérateur de début et la sentinelle de fin aient le même type et que la vue que vous utilisez ne répond pas à cette exigence (ou que vous ne savez pas si elle le fait), utilisez cet adaptateur de plage pour créer un common_view. Il garantit que le type de l’itérateur de début et le type de la sentinelle de fin sont identiques.

Exemple : common

// requires /std:c++20 or higher
#include <ranges>
#include <iostream>
#include <numeric>
#include <list>

int main()
{
    std::list<int> lst{1, 2, 3, 4, 5, 6, 7, 8, 9};

    auto firstFive = std::views::take(lst, 5); 
    // firstFive.begin(), firstFive.end() have different types: counted_iterator versus default_sentinel
    // auto r = std::accumulate(firstFive.begin(), firstFive.end(), 0); // Error: accumulate() requires firstFive.begin() and firstFive.end() types to be the same.
    
    auto common = std::views::common(firstFive); // create a common_view that has the same begin/end iterator types
    std::cout << std::accumulate(common.begin(), common.end(), 0); // Now you can call the API because the iterator types are the same. Outputs 15 (1+2+3+4+5) 
}
15

counted

Créez une vue des premiers count éléments d’une plage, à partir de l’emplacement spécifié.

template<class Iterator>
constexpr auto counted(Iterator&& it, iter_difference_t<Iterator> count);

Paramètres

DifferenceType
Type du nombre.

Iterator
Type de l’itérateur.

count
Nombre d’éléments à inclure dans la vue. Doit être non négatif.

  • Si count == 0, un vide span est retourné.
  • S’il count est supérieur au nombre d’éléments de la plage, le comportement n’est pas défini.

it
Itérateur à l’élément de la plage à commencer. Élément vers lequel pointe l’itérateur dans la vue créée.

Valeur retournée

Un span est retourné s’il s’agit it d’un contiguous_iterator tableau, de vecteurs et d’autres conteneurs qui stockent leurs éléments contigus. Sinon, un subrange est retourné.

Notes

Les éléments inclus sont [it, count).

Une fois la vue créée, le nombre d’éléments de la vue reste le même, même si la plage qu’elle a été créée à partir des modifications. Toutefois, si la plage sous-jacente change, l’accès aux éléments à partir de la vue peut entraîner un comportement non défini.

Exemple : counted

// requires /std:c++20 or later
#include <algorithm>
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto pos5 = std::ranges::find(v, 5);
    auto countedView = std::views::counted(pos5, 5);
    for (auto e : countedView) // outputs 5 6 7 8 9
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    // You can pass the range directly if it supports input_or_output_iterator, in which case
    // the count starts from the first element
    const char chars[] = { 'H','i',' ','t','h','e','r','e' };
    for (char c : std::views::counted(chars, 2))
    {
        std::cout << c; // outputs Hi
    }
}
5 6 7 8 9
Hi

drop

Créez une vue qui exclut les n premiers éléments d’une plage.

1) template<ranges::viewable_range R>
constexpr ranges::view auto drop(R&& rg, ranges::range_difference_t<R> count);

2) template<class DifferenceType>
constexpr /* range closure object */ drop(DifferenceType&& count);

Paramètres

DifferenceType
Type qui décrit le nombre d’éléments à ignorer.

count
Nombre d’éléments à supprimer à partir de l’avant de rg. Doit être non négatif.

  • Si count == 0, tous les éléments inclus rg sont retournés.
  • Si count elle est supérieure au nombre d’éléments dans rg, une vue vide est retournée.

R
Type de la plage.

rg
Plage utilisée pour créer la vue.

Valeur retournée

Vue de la plage sous-jacente, avec le nombre spécifié d’éléments supprimés du front.

Si vous spécifiez plus d’éléments à supprimer qu’il n’existe dans la plage sous-jacente, un empty_view élément est retourné.

La vue retournée est généralement, mais pas toujours, une spécialisation de drop_view. Plus précisément :

Notes

Une fois qu’elle a été créée, le nombre d’éléments dans la vue reste le même, même si la vue qu’elle a été créée à partir des modifications. Toutefois, si la vue sous-jacente change, l’accès aux éléments dans la vue retournée peut entraîner un comportement non défini.

drop est l’opposé de take.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | drop(5). Ou il peut être utilisé avec la syntaxe d’appel de fonction : drop(collection, 5) ou drop(5)(collection).

Exemple : drop

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{1, 2, 3, 4, 5};
    auto newView = std::views::drop(v, 3);
    for (auto e : newView) // 4 5
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    auto numbers = std::views::iota(0) | std::views::take(10); // build a view of 10 integers
    auto latterHalf = numbers | std::views::drop(5);
    for (auto i : latterHalf)
    {
        std::cout << i << ' '; // 5 6 7 8 9
    }
}
4 5
5 6 7 8 9

drop_while

Créez une vue qui contient les éléments d’une plage qui restent après les éléments de début qui correspondent à la condition spécifiée sont supprimés.

1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto drop_while(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ drop_while(P&& predicate);

Paramètres

R
Type de la plage.

predicate
Conditions qui déterminent quels éléments de début doivent être supprimés de la plage.

rg
Plage sous-jacente à partir de qui créer la vue.

Valeur retournée

Qui drop_while_view se compose des éléments qui restent lorsque les éléments de début qui correspondent au prédicat sont supprimés.

Notes

Arrête de supprimer des rg éléments dès que le prédicat retourne false.

drop_while est l’opposé de take_while.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | drop_while(predicate). Ou il peut être utilisé avec la syntaxe d’appel de fonction : drop_while(collection, predicate) ou drop_while(predicate)(collection).

Exemple : drop_while

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto myView = std::views::drop_while(
        v,
        [](int i) {return i >= 0; });
    print(myView); // -4 5 6

    auto myView2 = v | std::views::drop_while(
        [](int i) {return i < 5; });
    print(myView2); // 5 6
}
-4 5 6
5 6

elements

Créez un elements_view, qui est une vue de l’index sélectionné dans chaque valeur de type tuple dans une plage. Par exemple, en fonction d’une plage de std::tuple<string, int> valeurs, créez tous elements_view les string éléments de chaque tuple.

template<ranges::viewable_range R, size_t N>
constexpr ranges::view auto elements<N>(R&& rg);

Paramètres

N
Index de l’élément à sélectionner à partir de chaque valeur de type tuple à inclure dans la vue.

R
Type de la plage sous-jacente.

rg
Plage de valeurs de type tuple à partir de partir de l’affichage.

Valeur retournée

Qui elements_view se compose de l’index sélectionné dans chaque valeur de type tuple dans une collection.

Exemple : elements

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>

int main()
{
    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Create an elements_view of all the string elements from each tuple
    for (int const year : std::views::elements<1>(cpp_standards))
    {
        std::cout << year << ' '; // 2003 2011 2014 2017 1998 2020
    }
    std::cout << '\n';

    // Another way, using |: create an elements_view of all the int elements from each tuple
    for (auto&& name : cpp_standards | std::views::elements<0>)
    {
        std::cout << name << ' '; // C++03 C++11 C++14 C++17 C++98 c++20
    }
}
2003 2011 2014 2017 1998 2020
C++03 C++11 C++14 C++17 C++98 c++20

empty

Créez un empty_viewaffichage qui n’a aucun élément.

template<class T>
inline constexpr empty_view<T> empty{};

Paramètres

T
Type des éléments dans la vue. La vue a besoin d’un type d’élément, même s’il n’y a aucun élément.

Valeur retournée

Élément empty_view.

Notes

Un empty_view élément peut être utile lorsque vous appelez du code qui nécessite une vue, mais n’a pas besoin de traiter ses éléments.

Exemple : empty

// requires /std:c++20 or higher
#include <ranges>
#include <iostream>

int main()
{
    auto anEmptyView = std::views::empty<int>;
    bool isNotEmpty = (bool)anEmptyView;
    std::cout << boolalpha << isNotEmpty << "\n"; // false
}
false

filter

Créez une vue qui contient les éléments d’une plage qui correspondent à la condition spécifiée.

1) template<ranges::viewable_range R, class P>
    requires {filter_view(forward<R>(rg), forward<P>(predicate));}
constexpr ranges::view auto filter(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ filter(P&& predicate);

Paramètres

P
Type du prédicat.

predicate
Conditions qui déterminent les éléments à conserver dans la plage.

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

Valeur retournée

Qui filter_view contient les éléments d’une plage qui correspondent au prédicat.

Notes

Par souci d’efficacité, lorsque vous utilisez filter et transform avec un canal |, faites d’abord filter pour que seuls transform les éléments que vous avez l’intention de conserver.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | filter(predicate). Ou il peut être utilisé avec la syntaxe d’appel de fonction : filter(collection, predicate) ou filter(predicate)(collection).

Exemple : filter

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
    auto myView = std::views::filter(v, [](int i) {return i < 5; });
    print(myView); // 0 1 2 3 -4

    auto myView2 = v | std::views::filter([](int i) {return i < 5; }); // pipe syntax
    print(myView2); // 0 1 2 3 -4
}
0 1 2 3 -4
0 1 2 3 -4

iota

Créez une vue qui contient une séquence de valeurs croissantes. La séquence peut être limitée ou non.

template<class V>
constexpr ranges::view auto iota(V&& startValue); // create an unbounded sequence of incrementing values

template<class V, class E>
constexpr ranges::view auto iota(V&& startValue, E&& endValue); // create a bounded sequence of incrementing values

Paramètres

E
Type de la valeur de fin.

S
Type de la valeur de début.

startValue
Première valeur de la séquence.

endValue
Cette valeur est une valeur antérieure à la dernière valeur qui sera dans la séquence. Par exemple, std::views::iota(0, 5) génère une vue qui a les valeurs 0,1,2,3,4.

Valeur retournée

Une iota_view séquence de valeurs croissantes.

Notes

Pour une séquence non délimitée, le comportement n’est pas défini une fois la valeur maximale de son type de données atteinte.

Exemple : iota

// requires /std:c++20 or later
#include <ranges>
#include <iostream>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    // create an iota view with its range adaptor (preferred)
    print(std::views::iota(0, 5)); // outputs 0 1 2 3 4
    
    // create an iota_view class directly
    std::ranges::iota_view letters{'a', 'f'};
    print(letters); // a b c d e
}
0 1 2 3 4
a b c d e

istream

Créez une vue sur les éléments d’un flux.

template <class Val>
views::istream<Val>(str);

Paramètres

str
Objet de flux. Son type est dérivé d’une spécialisation de std::basic_istream.

Val
Type des éléments à extraire du flux.

Valeur retournée

Un basic_istream_view.

Cet adaptateur de plage est équivalent à ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str), où U est le type de str.

Exemple : istream

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <sstream>
#include <vector>

int main()
{
    std::istringstream doubles{"1.1 2.2 3.3 4.4 5.5"};
    for (const auto& elem : std::views::istream<double>(doubles))
    {
        std::cout << elem << ' '; // 1.1 2.2 3.3 4.4 5.5
    }
}
1.1 2.2 3.3 4.4 5.5

join

Créez une vue qui combine tous les éléments de plusieurs plages en une seule vue.

1) template <ranges::viewable_range R>
[[nodiscard]] constexpr ranges::view auto join(R&& rg) const noexcept;

2) inline constexpr /*range adaptor closure*/ join();

Paramètres

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

Valeur retournée

Qui join_view contient les éléments de toutes les plages de la plage sous-jacente.

Exemple : join

#include <iostream>
#include <vector>
#include <ranges>
#include <string>

int main()
{
    // a range of two ranges
    std::vector<std::string> rangeOfRanges[2]{{"C++20", "contains:"}, {"ranges", "modules", "concepts & more."}};

    for (const auto& elem : std::views::join(rangeOfRanges))
    {
        std::cout << elem << ' ';
    }
}
C++20 contains: ranges modules concepts & more.

Notes

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | join. Ou il peut être utilisé avec la syntaxe d’appel de fonction : join(collection).

keys

Créez un keys_view premier index dans chaque valeur de type tuple dans une collection. Cela est utile pour extraire des clés à partir de conteneurs associatifs. Par exemple, en fonction d’une plage de std::tuple<string, int>, créez une vue qui se compose de tous les string éléments de chaque tuple.

template <ranges::viewable_range R>
constexpr auto keys(R&& rg);

Paramètres

R
Type de la plage sous-jacente.

Valeur retournée

Qui keys_view se compose du premier index dans chaque valeur de type tuple dans la plage.

Exemple : keys

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    // ========== extract keys from a map

    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Extract all of the keys from the map
    for (std::string standards : std::views::keys(cpp_standards))
    {
        std::cout << standards << ' '; // C++03 C++11 C++14 C++17 C++98 C++20
    }
    std::cout << '\n';

    // ========== Extract keys from a pair

    std::vector<std::pair<std::string, int>> windows
    {
        {"Windows 1.0", 1985},
        {"Windows 2.0", 1987},
        {"Windows 3.0", 1990},
        {"Windows 3.1", 1992},
        {"Windows NT 3.1", 1993},
        {"Windows 95", 1995},
        {"Windows NT 4.0", 1996},
        {"Windows 95", 1995},
        {"Windows 98", 1998},
        {"Windows 1.0", 1985},
        {"Windows 2000", 2000}
    };
    
    // Another way to call the range adaptor is by using '|'
    for (std::string version : windows | std::views::keys)
    {
        std::cout << version << ' '; // Windows 1.0 Windows 2.0 Windows 3.0 ...
    }
}
C++03 C++11 C++14 C++17 C++98 C++20
Windows 1.0 Windows 2.0 Windows 3.0 Windows 3.1 Windows NT 3.1 Windows 95 Windows NT 4.0 Windows 95 Windows 98 Windows 1.0 Windows 2000

lazy_split

Fractionnez une plage en sous-plages en fonction d’un délimiteur. Le délimiteur peut être un élément unique ou une vue d’éléments.

1) template<viewable_range R, class Pattern>
constexpr view auto lazy_split(R&& rg, Pattern&& delimiter);

2) template<class Pattern>
constexpr /*range adaptor closure*/ lazy_split(Pattern&& delimiter);

Paramètres

delimiter
Valeur unique ou séquence de valeurs qui spécifient où fractionner la plage.

Pattern
Type du délimiteur.

R
Type de la plage à fractionner.

rg
Plage à fractionner.

Valeur retournée

Qui lazy_split_view contient une ou plusieurs sous-plages et est le résultat du fractionnement de la plage d’origine sur delimiter.

Notes

Le délimiteur ne fait pas partie du résultat. Par exemple, si vous fractionnez la plage 1,2,3 sur la valeur 2, vous obtenez deux sous-plages : 1 et 3.

Un adaptateur associé est split. Les principales différences entre [split_view](split-view-class.md) and lazy_split_view' sont les suivantes :

Affichage Peut fractionner une const plage Itérateur de plage
split_view non Prend en charge forward_range ou version ultérieure
lazy_split_view Oui input_range ou version ultérieure

Préférez split_view parce qu’il est plus efficace, sauf si vous devez fractionner une plage qui est const.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | lazy_split(delimiter). Ou il peut être utilisé avec la syntaxe d’appel de fonction : lazy_split(collection, delimiter) ou lazy_split(delimiter)(collection).

Exemple : lazy_split

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> rg{1, 2, 3, 1, 2, 3, 4, 5, 6};

    // split on a single element
    for (const auto& sub : rg | std::views::split(3))
    {
        // outputs:
        // 1 2
        // 1 2
        // 4 5 6
        for (const auto& elem : sub)
        {
            std::cout << elem << ' ';
        }
        std::cout << '\n';
    }

    // split on a sequence of elements
    int delimiters[] = {2, 3};
    for (const auto& subrange : std::views::split(rg, delimiters))
    {
        // outputs 1 1 4 5 6
        for (auto& i : subrange)
        {
            std::cout << i << " ";
        }
    }
}
1 2
1 2
4 5 6
1 1 4 5 6

reverse

Créez une vue des éléments d’une plage dans l’ordre inverse.

1) template<viewable_range R>
constexpr ranges::view auto reverse(R&& rg);

2) inline constexpr /*range adaptor closure*/ reverse();

Paramètres

R
Type de la plage sous-jacente à inverser.

rg
Plage à inverser.

Valeur retournée

Vue qui présente les éléments de la plage sous-jacente dans l’ordre inverse. La vue retournée est généralement, mais pas toujours, une spécialisation de reverse_view. Plus précisément :

  • S’il V s’agit d’une spécialisation, reverse_viewle résultat est la vue sous-jacente de l’argument. Un double inverse est une opération sans opération (aucune opération).
  • Si V la forme subrange<reverse_iterator<I>, reverse_iterator<I>>est présente, le résultat est un subrange itérateur non mis en forme. Un double inverse est une opération sans opération.
  • Sinon, le résultat est un reverse_view.

Notes

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | reverse. Ou il peut être utilisé avec la syntaxe d’appel de fonction : reverse(collection).

Exemple : reverse

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto rv = v | std::views::reverse; // using the pipe syntax  

    for (auto &&e : rv) // outputs 6 5 -4 3 2 1 0
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    // using the range adaptor without using the pipe syntax
    auto rv2 = std::views::reverse(v);
    for (auto &&e : rv2) // outputs 6 5 -4 3 2 1 0
    {
        std::cout << e << ' ';
    }
}
6 5 -4 3 2 1 0
6 5 -4 3 2 1 0

single

Créez un single_viewaffichage qui contient un élément.

template<class T>
constexpr ranges::view auto single(T&& t);

Paramètres

T
Type de l’élément dans la vue.

t
Valeur de l’élément à stocker dans la vue.

Valeur retournée

Qui single_view contient t.

Notes

Cette vue est utile à des fins de test, pour appeler du code qui doit être fourni avec une vue qui a au moins un élément dans celui-ci.

Exemple : single

// requires /std:c++20 or higher
#include <ranges>
#include <string>
#include <tuple>
#include <iostream>

int main()
{
    auto sv = std::views::single(7);
    std::cout << sv.front() << " " << *sv.data() << "\n"; // 7 7
    
    auto sv2 = std::views::single(<std::tuple<double, std::string>{6502, "8-bit"});
    std::cout << std::get<0>(sv2[0]) << " " << std::get<1>(sv2[0]) << "\n"; // 6502 8-bit
}
7 7
6502 8-bit

split

Fractionnez une vue en sous-plages en fonction d’un délimiteur. Le délimiteur peut être un élément unique ou une séquence d’éléments.

1) template<viewable_range R, class Pattern>
constexpr view auto split(R&& rg, Pattern&& delimiter);

2) template<class Pattern>
constexpr /*range adaptor closure*/ split(Pattern&& delimiter);

Paramètres

delimiter
Valeur unique ou séquence de valeurs qui spécifient où fractionner la plage.

Pattern
Type du délimiteur.

R
Type de la plage sous-jacente à fractionner.

rg
Plage à fractionner.

Valeur retournée

Qui split_view contient une ou plusieurs sous-plages.

Notes

Le délimiteur ne fait pas partie du résultat. Par exemple, si vous fractionnez la plage 1,2,3 sur la valeur 2, vous obtenez deux sous-plages : 1 et 3.

Un adaptateur associé est lazy_split. Les principales différences entre split_view et lazy_split_view sont les suivantes :

Affichage Peut fractionner une const plage Type de plage
split_view non Prend en charge forward_range ou version ultérieure
lazy_split_view Oui Prend en charge input_range ou version ultérieure

Préférez split_view parce qu’il est plus efficace, sauf si vous devez fractionner une plage qui est const.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | split(delimiter). Ou il peut être utilisé avec la syntaxe d’appel de fonction : split(collection, 5) ou split(5)(collection).

Exemple : split

// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> rg{ 1, 2, 3, 1, 2, 3, 4, 5, 6 };

    // split on a single element, 3
    for (const auto& sub : rg | std::views::split(3))
    {
        // This prints out:
        // 1,2
        // 4,5,6
        for (const auto& elem : sub)
        {
            std::cout << elem << ' ';
        }
        std::cout << '\n';
    }

    // split on a sequence of elements, 2,3
    int delimiters[] = {2, 3};
    for (const auto& subrange : std::views::split(rg, delimiters))
    {
        // outputs 1 1 4 5 6
        for (auto& i : subrange)
        {
            std::cout << i << " ";
        }
    }
}
1 2
1 2
4 5 6
1 1 4 5 6

take

Créez une vue qui contient le nombre spécifié d’éléments pris à partir de l’avant d’une plage.

1) template<ranges::viewable_range R>
constexpr ranges::view auto take(R&& rg, ranges::range_difference_type<R> count);

2) template<class DifferenceType>
constexpr /*range adaptor closure*/ take(DifferenceType&& count); 

Paramètres

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

count
Nombre d’éléments à prendre à partir de l’avant de rg.

Valeur retournée

La vue retournée est généralement, mais pas toujours, une spécialisation de take_view. Plus précisément :

Notes

Si vous spécifiez plus d’éléments à prendre qu’il n’existe, rgtous les éléments sont pris.

take est l’opposé de drop.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | take(5). Ou il peut être utilisé avec la syntaxe d’appel de fonction : take(5, collection) ou take(5)(collection).

Exemple : take

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::string s{ "abcdefg" };
    auto myView = std::views::take(s, 3);
    for (auto c : myView)
    {
        std::cout << c << ' '; // a b c
    }

    std::cout << std::endl;

    for (auto c : s | std::views::take(3)) // pipe syntax
    {
        std::cout << c << ' '; // a b c
    }
}
a b c
a b c

take_while

Créez une vue qui contient les éléments principaux d’une plage qui correspondent à la condition spécifiée.

1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto take_while(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ take_while(P&& predicate);

Paramètres

P
Type du prédicat.

predicate
Conditions qui déterminent les éléments de début à copier à partir de la plage.

R
Type de la plage sous-jacente.

rg
Plage à partir de l’affichage.

Valeur retournée

Qui take_while_view se compose des premiers count éléments qui répondent aux critères spécifiés dans la plage.

Notes

Arrête de rg prendre des éléments après que le prédicat retourne false ou que la plage manque d’éléments.

take_while est l’opposé de drop_while.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | take_while(pred). Ou il peut être utilisé avec la syntaxe d’appel de fonction : take_while(collection, pred) ou take_while(pred)(collection).

Exemple : take_while

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto myView = std::views::take_while(
        v, [](int i) {return i >= 0; });
    print(myView); // 0 1 2 3

    print(v | std::views::take_while( // 0 1 2 3 -4
        [](int i) {return i < 5; })); // pipe syntax
}
0 1 2 3
0 1 2 3 -4

transform

Créez une vue d’éléments, chacune d’elles étant une transformation d’un élément dans la plage spécifiée.

1) template<viewable_range R, class F>
constexpr ranges::view auto transform(R&& rg, F&& fun);

2) template<class F>
constexpr /*range adaptor closure*/ transform(F&& fun);

Paramètres

F
Type de l’objet de fonction à transformer les éléments.

R
Type de la plage sous-jacente.

fun
Fonction qui transforme les éléments.

rg
Plage à partir de l’affichage.

Valeur retournée

Qui transform_view contient les éléments transformés de rg.

Notes

Par souci d’efficacité, lorsque vous composez filter et transform, faites d’abord pour filter que seuls transform les éléments que vous avez l’intention de conserver.

Le code présenté précédemment sous la forme « 2) » peut être utilisé avec la syntaxe de canal : collection | transform(fun). Ou il peut être utilisé avec la syntaxe d’appel de fonction : transform(collection, fun) ou transform(fun)(collection).

Exemple : transform

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
    auto myView = std::views::transform(v, [](int i) {return i * 2; });
    print(myView); // 0 2 4 6 -8 10 12

    print(v | std::views::transform( // 0 2 4 6 -8 10 12
        [](int i) {return i * 2; })); // pipe syntax
}
0 2 4 6 -8 10 12
0 2 4 6 -8 10 12

values

Créez un values_view index qui se compose du deuxième index dans chaque valeur de type tuple dans une collection. Cela est utile pour afficher les valeurs d’un conteneur associatif. Par exemple, en fonction d’une plage de std::tuple<string, int> valeurs, créez une vue qui se compose de tous les int éléments de chaque tuple.

template <range::viewable_range R>
constexpr ranges::view auto values(R&& rg);

Paramètres

R
Type de la plage sous-jacente.

rg
Plage sous-jacente de valeurs de type tuple.

Valeur retournée

Intégré values_view à partir du deuxième index dans chaque valeur de type tuple dans la plage.

Exemple : values

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    // ========== working with a map

    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Extract all of the years from the map
    for (int years : std::views::values(cpp_standards))
    {
        std::cout << years << ' '; // 2003 2011 2014 2017 1998 2020
    }
    std::cout << '\n';

    // ========== working with pairs

    std::vector<std::pair<std::string, int>> windows
    {
        {"Windows 1.0", 1985},
        {"Windows 2.0", 1987},
        {"Windows 3.0", 1990},
        {"Windows 3.1", 1992},
        {"Windows NT 3.1", 1993},
        {"Windows 95", 1995},
        {"Windows NT 4.0", 1996},
        {"Windows 95", 1995},
        {"Windows 98", 1998},
        {"Windows 1.0", 1985},
        {"Windows 2000", 2000}
    };

    // Another way to call the range adaptor by using '|'
    // Create a values_view that contains the year from each pair
    for (int years : windows | std::views::values)
    {
        std::cout << years << ' '; // 1985 1987 1990 1992 ...
    }
}
2003 2011 2014 2017 1998 2020
1985 1987 1990 1992 1993 1995 1996 1995 1998 1985 2000

Alias de type d’adaptateur de plage

all_t

Fournit le type de la vue qui all retourne.

template <ranges::viewable_range R>
using all_t = decltype(views::all(std::declval<R>()));

Paramètres

R
Type de la plage sous-jacente.

Valeur retournée

Type de la vue qui all retourne : decltype(views::all(std::declval<R>())).

Exemple : all_t

#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
    auto myView = std::views::all(v);
    std::views::all_t<decltype((v))> &viewType = myView;
}

Voir aussi

<ranges>
<ranges> Concepts
Afficher les classes