Adattatori di intervallo
Gli adattatori di intervallo creano una visualizzazione (una delle classi View nello spazio dei std::views
nomi) da un intervallo. È consigliabile usare un adattatore per creare visualizzazioni anziché creare direttamente i tipi di visualizzazione. Gli adattatori sono il modo previsto per accedere alle visualizzazioni. Sono più facili da usare e, in alcuni casi, più efficienti rispetto alla creazione diretta di istanze dei tipi di visualizzazione.
Una visualizzazione è un oggetto leggero che fa riferimento agli elementi di un intervallo. Una visualizzazione può:
- Sono costituiti solo da determinati elementi di un intervallo.
- Rappresenta una trasformazione di elementi da un intervallo.
- Invertirsi o solo i primi
n
elementi di un intervallo. - Essere una combinazione delle cose precedenti.
Una visualizzazione è economica, O(1)
, per copiare, assegnare ed eliminare definitivamente, indipendentemente dal numero di elementi coinvolti. Si consideri l'esempio seguente:
// 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
Il primo adattatore di intervallo, filter
, fornisce una visualizzazione che contiene gli elementi da input
cui sono divisibili per tre. L'altro adattatore di intervallo, transform
, accetta la visualizzazione che contiene gli elementi divisibile per tre e fornisce una visualizzazione del quadrato di tali elementi.
Quando un adattatore di intervallo produce una visualizzazione, non comporta il costo della trasformazione di ogni elemento nell'intervallo per produrre tale visualizzazione. Il costo per elaborare un elemento nella visualizzazione viene pagato solo quando si accede a tale elemento.
La creazione di una vista è la preparazione per eseguire operazioni future. Nell'esempio precedente, la creazione della vista non comporta la ricerca di tutti gli elementi divisibile per tre o squaring di tali elementi. Il lavoro avviene solo quando si accede a un elemento nella visualizzazione.
Gli elementi di una visualizzazione sono in genere gli elementi effettivi dell'intervallo utilizzato per creare la vista. La vista in genere non è proprietaria degli elementi; si riferisce solo a essi, ad eccezione di owning_view
. La modifica di un elemento modifica l'elemento nell'intervallo da cui è stata creata la visualizzazione. L'esempio seguente illustra questo comportamento:
#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
}
}
Gli adattatori di intervallo sono disponibili in molte forme. Ad esempio, sono disponibili adattatori di intervallo che consentono di produrre una visualizzazione in base a:
- Filtro di un altro intervallo basato su un predicato (
filter
). - Trasformazione degli elementi in un intervallo (
transform
). - Divisione di un intervallo (
split
).
Gli adattatori di intervallo possono essere concatenati (composti). Ecco dove la potenza e la flessibilità degli intervalli sono più evidenti. La composizione degli adattatori di intervallo consente di risolvere un problema principale con gli algoritmi STL (Standard Template Library) precedenti, ovvero che non sono facili da concatenare.
Gli adattatori di intervallo seguenti sono disponibili nello spazio dei std::views
nomi . Lo std::views
spazio dei nomi è un alias pratico per std::ranges::views
.
Adattatore di intervallo | Descrizione |
---|---|
all C++20 |
Creare una vista che fa riferimento a un intervallo e ai relativi elementi. |
common C++20 |
Creare una vista con gli stessi tipi di iteratore e sentinel da un intervallo che non lo fa. |
counted C++20 |
Creare una visualizzazione dei primi n elementi di un intervallo, a partire dalla posizione specificata. |
drop C++20 |
Creare una visualizzazione da un'altra visualizzazione, ignorando il numero specificato di elementi dalla parte anteriore. |
drop_while C++20 |
Creare una visualizzazione contenente gli elementi di un intervallo che rimangono dopo l'eliminazione degli elementi iniziali che corrispondono alla condizione specificata. |
elements C++20 |
Creare una vista dell'indice selezionato in ogni valore simile a una tupla in un intervallo. |
empty C++20 |
Creare una vista senza elementi. |
filter C++20 |
Creare una vista contenente gli elementi di un intervallo che corrispondono alla condizione specificata. |
iota C++20 |
Creare una vista contenente una sequenza di valori crescenti. |
istream C++20 |
Creare una visualizzazione sugli elementi di un flusso. |
join C++20 |
Creare una visualizzazione che combina tutti gli elementi di più intervalli in una singola visualizzazione. |
keys C++20 |
Creare una vista del primo indice in ogni valore simile a una tupla in una raccolta. |
lazy_split C++20 |
Dividere una visualizzazione in intervalli secondari in base a un delimitatore. |
reverse C++20 |
Creare una visualizzazione degli elementi di un intervallo in ordine inverso. |
single C++20 |
Creare una vista contenente un elemento. |
split C++20 |
Dividere una visualizzazione in intervalli secondari in base a un delimitatore. |
take C++20 |
Creare una visualizzazione dei primi n elementi da un'altra visualizzazione. |
take_while C++20 |
Creare una vista contenente gli elementi iniziali di un intervallo che corrispondono alla condizione specificata. |
transform C++20 |
Creare una visualizzazione di elementi trasformati da un'altra visualizzazione. |
values C++20 |
Creare una vista del secondo indice in ogni valore simile a una tupla in una raccolta. |
Nella tabella precedente, un adattatore di intervallo viene in genere descritto come accettare un intervallo e produrre una vista. Per essere precisi, gli adattatori di intervallo hanno un argomento di intervallo che accetta uno dei seguenti elementi:
- Il
cv-unqualified
tipo modellaview
e l'argomento è un rvalue o è copiabile. - Quando si passa l'argomento come lvalue, deve modellare
range
e vivere finché la vista. - Quando si passa l'argomento come rvalue, ad esempio quando si chiama
owning_view
, deve modellarerange
emovable
.
Le funzioni di adattatore di intervallo sono in genere oggetti funzione, che hanno un aspetto simile alle chiamate di funzione e applicano vincoli sui tipi che possono essere passati.
È possibile passare adattatori di intervallo e il risultato delle operazioni pipe (|
) al codice che prevede oggetti funzione. Nell'esempio seguente, la visualizzazione creata dall'adattatore split
di intervallo viene passata all'adattatore transform
di intervallo come se fosse una chiamata di funzione, perché l'adattatore transform
di intervallo è un oggetto funzione.
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
Creare una visualizzazione di tutti gli elementi in un intervallo.
template <ranges::viewable_range R>
constexpr ranges::view auto all(R&& rg) const noexcept;
Parametri
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
Valore restituito
- Se
rg
è già una visualizzazione, una copia dirg
. - Se
rg
è un lvalue non view, un oggettoref_view
che fa riferimento arg
. (La durata della visualizzazione è associata alla durata dirg
.) - Se
rg
è un rvalue non visualizzazione, ad esempio un oggetto temporaneo o è il risultato del passaggio dell'intervallo astd::move
, un oggettoowning_view
.
Usare std::views::all_t<decltype((rg))>
per ottenere il tipo della visualizzazione restituita.
Osservazioni:
Questo adattatore di intervallo è il modo migliore per convertire un intervallo in una visualizzazione. Un motivo per creare una visualizzazione da un intervallo consiste nel passarlo per valore a basso costo, se il passaggio dell'intervallo per valore potrebbe essere costoso.
Ottenere una visualizzazione per un intervallo è un'alternativa utile al passaggio di un intervallo di pesi massimi per valore perché le visualizzazioni sono poco costose per creare, copiare e distruggere. Un'eccezione possibile è owning_view
, ovvero una vista proprietaria dell'intervallo sottostante.
In generale, lo scenario peggiore per l'eliminazione di una visualizzazione presenta O(N)
complessità per il numero di elementi nell'intervallo. Anche se si eliminano K
copie di visualizzazione con N
elementi, la complessità totale è ancora O(N)
perché l'intervallo sottostante viene eliminato una sola volta.
Esempio: 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
Creare una vista con lo stesso iteratore iniziale e lo stesso tipo di sentinel da un intervallo che potrebbe non essere.
template <ranges::viewable_range R>
constexpr ranges::view auto common(R&& rg) const noexcept;
Parametri
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
Valore restituito
views::all(rg)
serg
è un intervallo con lo stesso tipo di iteratore e sentinel.common_view(views::all(rg))
serg
ha tipi di iteratore e sentinel diversi.
Osservazioni:
Quando un'API richiede che l'iteratore iniziale e l'endpoint sentinel abbiano lo stesso tipo e che la visualizzazione in uso non soddisfi tale requisito (o non si sa se lo fa), usare questo adattatore di intervallo per creare un oggetto common_view
. Garantisce che il tipo dell'iteratore iniziale e il tipo di sentinel finale siano gli stessi.
Esempio: 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
Creare una visualizzazione dei primi count
elementi di un intervallo, a partire dalla posizione specificata.
template<class Iterator>
constexpr auto counted(Iterator&& it, iter_difference_t<Iterator> count);
Parametri
DifferenceType
Tipo del conteggio.
Iterator
Tipo dell'iteratore.
count
Numero di elementi da includere nella visualizzazione. Deve essere non negativo.
- Se
count == 0
, viene restituito un valore vuotospan
. - Se
count
è maggiore del numero di elementi nell'intervallo, il comportamento non è definito.
it
Iteratore dell'elemento nell'intervallo da cui iniziare. L'elemento a cui punta l'iteratore è incluso nella visualizzazione creata.
Valore restituito
Viene span
restituito se it
è un contiguous_iterator
oggetto per matrici, vettori e altri contenitori che archiviano i relativi elementi in modo contiguo. In caso contrario, viene restituito un oggetto subrange
.
Osservazioni:
Gli elementi inclusi sono [it, count)
.
Dopo aver creato la visualizzazione, il numero di elementi nella visualizzazione rimane invariato, anche se l'intervallo creato dalle modifiche. Tuttavia, se l'intervallo sottostante cambia, l'accesso agli elementi dalla visualizzazione potrebbe comportare un comportamento indefinito.
Esempio: 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
Creare una vista che esclude i primi n elementi di un intervallo.
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);
Parametri
DifferenceType
Tipo che descrive il numero di elementi da ignorare.
count
Numero di elementi da eliminare dalla parte anteriore di rg
. Deve essere non negativo.
- Se
count == 0
, vengono restituiti tutti gli elementi inrg
. - Se
count
è maggiore del numero di elementi inrg
, viene restituita una visualizzazione vuota.
R
Tipo dell'intervallo.
rg
Intervallo utilizzato per creare la visualizzazione.
Valore restituito
Visualizzazione dell'intervallo sottostante, con il numero specificato di elementi eliminati dalla parte anteriore.
Se si specificano più elementi da eliminare rispetto all'intervallo sottostante, viene restituito un oggetto empty_view
.
La vista restituita è in genere, ma non sempre, una specializzazione di drop_view
. Ovvero:
- Se
V
è una specializzazione diempty_view
o è una specializzazione dispan
,basic_string_view
,iota_view
osubrange
che è siarandom_access_range
esized_range
, il risultato è una specializzazione diV
. - In caso contrario, il risultato è .
drop_view
Osservazioni:
Dopo la creazione, il numero di elementi nella visualizzazione rimane invariato anche se la visualizzazione creata dalle modifiche. Tuttavia, se la visualizzazione sottostante cambia, l'accesso agli elementi nella visualizzazione restituita potrebbe comportare un comportamento non definito.
drop
è l'opposto di take
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | drop(5)
. Oppure può essere usato con la sintassi delle chiamate di funzione: drop(collection, 5)
o drop(5)(collection)
.
Esempio: 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
Creare una visualizzazione contenente gli elementi di un intervallo che rimangono dopo l'eliminazione degli elementi iniziali che corrispondono alla condizione specificata.
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);
Parametri
R
Tipo dell'intervallo.
predicate
Condizioni che determinano quali elementi iniziali eliminare dall'intervallo.
rg
Intervallo sottostante da cui creare la vista.
Valore restituito
Oggetto drop_while_view
costituito dagli elementi che rimangono quando vengono eliminati gli elementi iniziali che corrispondono al predicato.
Osservazioni:
Interrompe l'eliminazione di elementi da rg
non appena il predicato restituisce false
.
drop_while
è l'opposto di take_while
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | drop_while(predicate)
. Oppure può essere usato con la sintassi delle chiamate di funzione: drop_while(collection, predicate)
o drop_while(predicate)(collection)
.
Esempio: 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
Creare un elements_view
oggetto , ovvero una vista dell'indice selezionato in ogni valore simile a una tupla in un intervallo. Ad esempio, dato un intervallo di std::tuple<string, int>
valori, creare un elements_view
oggetto di tutti gli string
elementi di ogni tupla.
template<ranges::viewable_range R, size_t N>
constexpr ranges::view auto elements<N>(R&& rg);
Parametri
N
Indice dell'elemento da selezionare da ogni valore simile a una tupla da includere nella vista.
R
Tipo dell'intervallo sottostante.
rg
Intervallo di valori simili a tuple da cui creare la vista.
Valore restituito
Oggetto elements_view
costituito dall'indice selezionato in ogni valore simile a una tupla in una raccolta.
Esempio: 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
Creare un oggetto empty_view
, ovvero una vista senza elementi.
template<class T>
inline constexpr empty_view<T> empty{};
Parametri
T
Tipo degli elementi nella visualizzazione. La vista richiede un tipo di elemento, anche se non sono presenti elementi.
Valore restituito
Oggetto empty_view
.
Osservazioni:
Un empty_view
può essere utile quando si chiama il codice che richiede una visualizzazione, ma non è necessario elaborare alcun elemento.
Esempio: 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
Creare una vista contenente gli elementi di un intervallo che corrispondono alla condizione specificata.
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);
Parametri
P
Tipo del predicato.
predicate
Condizioni che determinano quali elementi mantenere nell'intervallo.
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
Valore restituito
Oggetto filter_view
contenente gli elementi di un intervallo che corrispondono al predicato.
Osservazioni:
Per motivi di efficienza, quando si usa filter
e insieme a una pipe |
, eseguire la filter
prima in modo che solo transform
gli elementi che si intende transform
mantenere.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | filter(predicate)
. Oppure può essere usato con la sintassi delle chiamate di funzione: filter(collection, predicate)
o filter(predicate)(collection)
.
Esempio: 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
Creare una vista contenente una sequenza di valori crescenti. La sequenza può essere delimitata o meno.
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
Parametri
E
Tipo del valore finale.
S
Tipo del valore iniziale.
startValue
Primo valore nella sequenza.
endValue
Questo valore è passato dall'ultimo valore che sarà nella sequenza. Ad esempio, std::views::iota(0, 5)
genera una vista con i valori 0,1,2,3,4
.
Valore restituito
Oggetto iota_view
di una sequenza di valori crescenti.
Osservazioni:
Per una sequenza non associato, il comportamento non è definito dopo il raggiungimento del valore massimo del relativo tipo di dati.
Esempio: 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
Creare una visualizzazione sugli elementi di un flusso.
template <class Val>
views::istream<Val>(str);
Parametri
str
Oggetto di flusso. Il tipo è derivato da una specializzazione di std::basic_istream
.
Val
Tipo degli elementi da estrarre dal flusso.
Valore restituito
Un oggetto basic_istream_view
.
Questo adattatore di intervallo equivale a ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str)
, dove U
è il tipo di str
.
Esempio: 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
Creare una visualizzazione che combina tutti gli elementi di più intervalli in una singola visualizzazione.
1) template <ranges::viewable_range R>
[[nodiscard]] constexpr ranges::view auto join(R&& rg) const noexcept;
2) inline constexpr /*range adaptor closure*/ join();
Parametri
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
Valore restituito
Oggetto join_view
contenente gli elementi di tutti gli intervalli nell'intervallo sottostante.
Esempio: 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.
Osservazioni:
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | join
. In alternativa, può essere usato con la sintassi delle chiamate di funzione: join(collection)
.
keys
Creare un keys_view
oggetto del primo indice in ogni valore simile a una tupla in una raccolta. Ciò è utile per estrarre le chiavi dai contenitori associativi. Ad esempio, dato un intervallo di std::tuple<string, int>
, creare una vista costituita da tutti gli string
elementi di ogni tupla.
template <ranges::viewable_range R>
constexpr auto keys(R&& rg);
Parametri
R
Tipo dell'intervallo sottostante.
Valore restituito
Oggetto keys_view
costituito dal primo indice in ogni valore di tupla nell'intervallo.
Esempio: 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
Dividere un intervallo in intervalli secondari in base a un delimitatore. Il delimitatore può essere un singolo elemento o una visualizzazione di elementi.
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);
Parametri
delimiter
Valore singolo o sequenza di valori che specificano dove suddividere l'intervallo.
Pattern
Tipo del delimitatore.
R
Tipo dell'intervallo da dividere.
rg
Intervallo da dividere.
Valore restituito
Oggetto lazy_split_view
contenente uno o più intervalli secondari ed è il risultato della divisione dell'intervallo originale in delimiter
.
Osservazioni:
Il delimitatore non fa parte del risultato. Ad esempio, se si divide l'intervallo 1,2,3
sul valore 2
, si ottengono due intervalli secondari: 1
e 3
.
Un adattatore correlato è split
. Le differenze principali tra [split_view](split-view-class.md) and
lazy_split_view' sono:
Visualizza | Può dividere un const intervallo |
Iteratore di intervallo |
---|---|---|
split_view |
no | Supporta forward_range o versione successiva |
lazy_split_view |
yes | input_range o superiore |
Preferisce split_view
perché è più efficiente, a meno che non sia necessario dividere un intervallo che sia const
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | lazy_split(delimiter)
. Oppure può essere usato con la sintassi delle chiamate di funzione: lazy_split(collection, delimiter)
o lazy_split(delimiter)(collection)
.
Esempio: 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
Creare una visualizzazione degli elementi di un intervallo in ordine inverso.
1) template<viewable_range R>
constexpr ranges::view auto reverse(R&& rg);
2) inline constexpr /*range adaptor closure*/ reverse();
Parametri
R
Tipo dell'intervallo sottostante da invertire.
rg
Intervallo da invertire.
Valore restituito
Visualizzazione che presenta gli elementi dell'intervallo sottostante in ordine inverso. La vista restituita è in genere, ma non sempre, una specializzazione di reverse_view
. Ovvero:
- Se
V
è una specializzazione direverse_view
, il risultato è la visualizzazione sottostante dell'argomento. Un doppio inverso è un no-op (nessuna operazione). - Se
V
ha il formatosubrange<reverse_iterator<I>, reverse_iterator<I>>
, il risultato è unosubrange
degli iteratori non compressi. Un doppio inverso è un no-op. - In caso contrario, il risultato è .
reverse_view
Osservazioni:
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | reverse
. In alternativa, può essere usato con la sintassi delle chiamate di funzione: reverse(collection)
.
Esempio: 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
Creare un single_view
oggetto , ovvero una vista contenente un elemento.
template<class T>
constexpr ranges::view auto single(T&& t);
Parametri
T
Tipo dell'elemento nella visualizzazione.
t
Valore dell'elemento da archiviare nella visualizzazione.
Valore restituito
Oggetto single_view
contenente t
.
Osservazioni:
Questa visualizzazione è utile a scopo di test, per chiamare il codice che deve essere fornito con una visualizzazione che include almeno un elemento.
Esempio: 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
Dividere una visualizzazione in intervalli secondari in base a un delimitatore. Il delimitatore può essere un singolo elemento o una sequenza di elementi.
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);
Parametri
delimiter
Valore singolo o sequenza di valori che specificano dove suddividere l'intervallo.
Pattern
Tipo del delimitatore.
R
Tipo dell'intervallo sottostante da dividere.
rg
Intervallo da dividere.
Valore restituito
Oggetto split_view
contenente uno o più intervalli secondari.
Osservazioni:
Il delimitatore non fa parte del risultato. Ad esempio, se si divide l'intervallo 1,2,3
sul valore 2
, si ottengono due intervalli secondari: 1
e 3
.
Un adattatore correlato è lazy_split
. Le principali differenze tra split_view
e lazy_split_view
sono:
Visualizza | Può dividere un const intervallo |
Tipo di intervallo |
---|---|---|
split_view |
no | Supporta forward_range o versione successiva |
lazy_split_view |
yes | Supporta input_range o versione successiva |
Preferisce split_view
perché è più efficiente, a meno che non sia necessario dividere un intervallo che sia const
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | split(delimiter)
. Oppure può essere usato con la sintassi delle chiamate di funzione: split(collection, 5)
o split(5)(collection)
.
Esempio: 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
Creare una visualizzazione che contiene il numero specificato di elementi ricavati dalla parte anteriore di un intervallo.
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);
Parametri
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
count
Numero di elementi da accettare dalla parte anteriore di rg
.
Valore restituito
La vista restituita è in genere, ma non sempre, una specializzazione di take_view
. In particolare:
- Se
V
è una specializzazione diempty_view
o è una specializzazione dispan
,basic_string_view
,iota_view
osubrange
che è siarandom_access_range
esized_range
, il risultato è una specializzazione diV
. - In caso contrario, il risultato è .
take_view
Osservazioni:
Se si specificano più elementi da accettare rispetto all'esistenza in rg
, vengono acquisiti tutti gli elementi.
take
è l'opposto di drop
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | take(5)
. Oppure può essere usato con la sintassi delle chiamate di funzione: take(5, collection)
o take(5)(collection)
.
Esempio: 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
Creare una vista contenente gli elementi iniziali di un intervallo che corrispondono alla condizione specificata.
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);
Parametri
P
Tipo del predicato.
predicate
Condizioni che determinano quali elementi iniziali copiare dall'intervallo.
R
Tipo dell'intervallo sottostante.
rg
Intervallo da cui creare la vista.
Valore restituito
Oggetto take_while_view
costituito dai primi count
elementi che soddisfano i criteri specificati nell'intervallo.
Osservazioni:
Interrompe l'acquisizione di elementi da rg
dopo che il predicato restituisce false
o l'intervallo esaurisce gli elementi.
take_while
è l'opposto di drop_while
.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | take_while(pred)
. Oppure può essere usato con la sintassi delle chiamate di funzione: take_while(collection, pred)
o take_while(pred)(collection)
.
Esempio: 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
Creare una visualizzazione degli elementi, ognuno dei quali è una trasformazione di un elemento nell'intervallo specificato.
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);
Parametri
F
Tipo dell'oggetto funzione da trasformare gli elementi.
R
Tipo dell'intervallo sottostante.
fun
Funzione che trasforma gli elementi.
rg
Intervallo da cui creare la vista.
Valore restituito
Oggetto transform_view
contenente gli elementi trasformati di rg
.
Osservazioni:
Per motivi di efficienza, quando si compone filter
e transform
, fare il filter
primo in modo che solo transform
gli elementi che si intende mantenere.
Il codice illustrato in precedenza come "2)" può essere usato con la sintassi della pipe: collection | transform(fun)
. Oppure può essere usato con la sintassi delle chiamate di funzione: transform(collection, fun)
o transform(fun)(collection)
.
Esempio: 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
Creare un values_view
oggetto costituito dal secondo indice in ogni valore simile a una tupla in una raccolta. Ciò è utile per visualizzare i valori in un contenitore associativo. Ad esempio, dato un intervallo di std::tuple<string, int>
valori, creare una vista costituita da tutti gli int
elementi di ogni tupla.
template <range::viewable_range R>
constexpr ranges::view auto values(R&& rg);
Parametri
R
Tipo dell'intervallo sottostante.
rg
Intervallo sottostante di valori simili a tuple.
Valore restituito
Oggetto values_view
compilato dal secondo indice in ogni valore simile a una tupla nell'intervallo.
Esempio: 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 del tipo di adattatore di intervallo
all_t
Fornisce il tipo di visualizzazione restituito all
.
template <ranges::viewable_range R>
using all_t = decltype(views::all(std::declval<R>()));
Parametri
R
Tipo dell'intervallo sottostante.
Valore restituito
Tipo della vista che all
restituisce: decltype(views::all(std::declval<R>()))
.
Esempio: 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;
}