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, filter
fournit une vue qui contient les éléments de input
ce qui sont divisibles par trois. L’autre adaptateur de plage, transform
prend 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 |
---|---|
all C++20 |
Créez une vue qui fait référence à une plage et à ses éléments. |
common C++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. |
counted C++20 |
Créez une vue des n premiers éléments d’une plage, à partir de l’emplacement spécifié. |
drop C++20 |
Créez une vue à partir d’une autre vue, en ignorant le nombre spécifié d’éléments à partir de l’avant. |
drop_while C++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. |
elements C++20 |
Créez une vue de l’index sélectionné dans chaque valeur de type tuple dans une plage. |
empty C++20 |
Créez une vue qui n’a aucun élément. |
filter C++20 |
Créez une vue qui contient les éléments d’une plage qui correspondent à la condition spécifiée. |
iota C++20 |
Créez une vue qui contient une séquence de valeurs croissantes. |
istream C++20 |
Créez une vue sur les éléments d’un flux. |
join C++20 |
Créez une vue qui combine tous les éléments de plusieurs plages en une seule vue. |
keys C++20 |
Créez une vue du premier index dans chaque valeur de type tuple dans une collection. |
lazy_split C++20 |
Fractionnez une vue en sous-plages en fonction d’un délimiteur. |
reverse C++20 |
Créez une vue des éléments d’une plage dans l’ordre inverse. |
single C++20 |
Créez une vue qui contient un élément. |
split C++20 |
Fractionnez une vue en sous-plages en fonction d’un délimiteur. |
take C++20 |
Créez une vue des premiers n éléments d’une autre vue. |
take_while C++20 |
Créez une vue qui contient les éléments principaux d’une plage qui correspondent à la condition spécifiée. |
transform C++20 |
Créez une vue des éléments transformés à partir d’une autre vue. |
values C++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èlesview
de 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éliserrange
etmovable
.
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 derg
. - S’il s’agit
rg
d’une valeur lvalue non-view, quiref_view
fait référence àrg
. (La durée de vie de la vue est liée à la durée de vie derg
.) - 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
, unowning_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’agitrg
d’une plage avec le même itérateur et le même type de sentinelle.common_view(views::all(rg))
s’ilrg
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 videspan
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 inclusrg
sont retournés. - Si
count
elle est supérieure au nombre d’éléments dansrg
, 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 :
- Si
V
est une spécialisation deempty_view
, ou est une spécialisation despan
,basic_string_view
,iota_view
ousubrange
qui est à la foisrandom_access_range
etsized_range
, le résultat est une spécialisation deV
. - Sinon, le résultat est un
drop_view
.
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_view
affichage 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
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_view
le 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 formesubrange<reverse_iterator<I>, reverse_iterator<I>>
est présente, le résultat est unsubrange
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_view
affichage 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 :
- Si
V
est une spécialisation deempty_view
, ou est une spécialisation despan
,basic_string_view
,iota_view
ousubrange
qui est à la foisrandom_access_range
etsized_range
, le résultat est une spécialisation deV
. - Sinon, le résultat est un
take_view
.
Notes
Si vous spécifiez plus d’éléments à prendre qu’il n’existe, rg
tous 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;
}