Sdílet prostřednictvím


Adaptéry rozsahu

Adaptéry rozsahu vytvářejí zobrazení (jednu z tříd zobrazení v std::views oboru názvů) z rozsahu. Místo přímého vytváření typů zobrazení doporučujeme použít adaptér. Adaptéry představují zamýšlený způsob přístupu k zobrazením. Snadněji se používají a v některých případech efektivnější než přímé vytváření instancí typů zobrazení.

Zobrazení je jednoduchý objekt, který odkazuje na prvky z rozsahu. Zobrazení může:

  • Skládá se pouze z určitých prvků z rozsahu.
  • Představuje transformaci prvků z rozsahu.
  • Být obrácený rozsah nebo pouze první n prvky oblasti.
  • Buďte kombinací předchozích věcí.

Zobrazení je levné, O(1)kopírovat, přiřazovat a zničit - bez ohledu na to, kolik prvků je zapojeno. Představte si následující příklad:

// 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

První adaptér rozsahu , filterposkytuje zobrazení, které obsahuje prvky z input , které jsou dělitelné třemi. Druhý adaptér rozsahu , transformbere zobrazení, které obsahuje prvky dělitelné třemi a poskytuje pohled na čtverec těchto prvků.

Když adaptér rozsahu vytvoří zobrazení, neúčtují se náklady na transformaci každého prvku v rozsahu, aby toto zobrazení vytvořilo. Náklady na zpracování elementu v zobrazení se platí pouze v případech, kdy k ho přistupujete.

Vytvoření zobrazení je příprava na práci v budoucnu. V předchozím příkladu vytvoření zobrazení nemá za následek nalezení všech prvků dělitelných třemi nebo squaringem těchto prvků. Práce probíhá pouze v případě, že přistupujete k prvku v zobrazení.

Prvky zobrazení jsou obvykle skutečnými prvky oblasti použité k vytvoření zobrazení. Zobrazení obvykle nevlastní prvky; pouze odkazuje na ně, s výjimkou owning_view. Změna elementu změní tento prvek v oblasti, ze které bylo zobrazení vytvořeno. Následující příklad ukazuje toto chování:

#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
    }
}

Adaptéry rozsahu mají mnoho forem. Existují například adaptéry rozsahu, které umožňují vytvořit zobrazení podle:

  • Filtrování jiné oblasti na základě predikátu (filter).
  • Transformace prvků v oblasti (transform).
  • Rozdělení oblasti (split).

Adaptéry rozsahu mohou být zřetězený (složené). Tady je nejvýraznější výkon a flexibilita rozsahů. Vytváření adaptérů rozsahu umožňuje překonat základní problém s předchozími algoritmy STL (Standard Template Library), což znamená, že není snadné je zřetězení dohromady.

V oboru názvů jsou k dispozici následující adaptéry rozsahu std::views . Obor std::views názvů je alias pohodlí pro std::ranges::views.

Adaptér rozsahu Popis
allC++20 Vytvořte zobrazení, které odkazuje na oblast a její prvky.
commonC++20 Vytvořte zobrazení se stejnými typy iterátoru a sentinelu z oblasti, která ne.
countedC++20 Vytvořte zobrazení prvních n prvků rozsahu počínaje zadaným umístěním.
dropC++20 Vytvořte zobrazení z jiného zobrazení a přeskočí zadaný počet prvků z přední části.
drop_whileC++20 Vytvořte zobrazení obsahující prvky oblasti, které zůstanou za úvodními prvky, které odpovídají zadané podmínce, se zahodí.
elementsC++20 Vytvořte zobrazení vybraného indexu do každé hodnoty podobné řazené kolekci členů v oblasti.
emptyC++20 Vytvořte zobrazení, které neobsahuje žádné prvky.
filterC++20 Vytvořte zobrazení obsahující prvky oblasti, které odpovídají zadané podmínce.
iotaC++20 Vytvořte zobrazení, které obsahuje posloupnost rostoucích hodnot.
istreamC++20 Vytvořte zobrazení nad prvky datového proudu.
joinC++20 Vytvořte zobrazení, které kombinuje všechny prvky více oblastí do jednoho zobrazení.
keysC++20 Vytvořte zobrazení prvního indexu do každé hodnoty podobné řazené kolekci členů v kolekci.
lazy_splitC++20 Rozdělte zobrazení na podranges na základě oddělovače.
reverseC++20 Umožňuje vytvořit zobrazení prvků oblasti v obráceném pořadí.
singleC++20 Vytvořte zobrazení, které obsahuje jeden prvek.
splitC++20 Rozdělte zobrazení na podranges na základě oddělovače.
takeC++20 Vytvořte zobrazení prvních n prvků z jiného zobrazení.
take_whileC++20 Vytvořte zobrazení, které obsahuje úvodní prvky oblasti, které odpovídají zadané podmínce.
transformC++20 Umožňuje vytvořit zobrazení transformovaných prvků z jiného zobrazení.
valuesC++20 Vytvořte zobrazení druhého indexu do každé hodnoty podobné řazené kolekci členů v kolekci.

V předchozí tabulce se adaptér rozsahu obvykle popisuje jako oblast a vytváří zobrazení. Aby byly přesné, adaptéry rozsahu mají argument rozsahu, který přijímá jednu z následujících možností:

  • Modely cv-unqualified typů viewa argument je hodnota rvalue nebo je možné ho kopírovat.
  • Když předáte argument jako lvalue, musí modelovat range a žít tak dlouho, dokud zobrazení.
  • Když předáte argument jako rvalue, například při volání owning_view, musí modelovat range a movable.

Funkce adaptéru rozsahu jsou obvykle objekty funkcí, které vypadají jako volání funkce a vynucují omezení typů, které lze předat.

Adaptéry rozsahu a výsledek operací potrubí (|) můžete předat kódu, který očekává objekty funkce. V následujícím příkladu je zobrazení, které adaptér rozsahu split vytvoří, předán adaptér rozsahu adaptéru transform , jako by volání funkce, protože transform adaptér rozsahu je objekt funkce.

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

Umožňuje vytvořit zobrazení všech prvků v oblasti.

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

Parametry

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

  • Pokud rg je již zobrazení, kopie souboru rg.
  • Je-li rg hodnota bez zobrazení lvalue, ref_view která odkazuje na rg. (Doba života zobrazení je svázaná s životností rg.)
  • Pokud rg je hodnota rvalue, jako je dočasný objekt, nebo je výsledkem předání rozsahu do std::move, an owning_view.

Slouží std::views::all_t<decltype((rg))> k získání typu vráceného zobrazení.

Poznámky

Tento adaptér rozsahu je nejlepší způsob, jak převést rozsah na zobrazení. Jedním z důvodů, proč vytvořit zobrazení z rozsahu, je předat ho podle hodnoty s nízkými náklady, pokud by předání rozsahu podle hodnoty mohlo být nákladné.

Získání zobrazení pro rozsah je užitečnou alternativou k předání rozsahu těžké váhy podle hodnoty, protože zobrazení jsou levná pro vytváření, kopírování a zničení. Možnou výjimkou je owning_viewzobrazení, které vlastní podkladovou oblast.

Obecně platí, že nejhorší scénář pro zničení zobrazení má O(N) složitost počtu prvků v rozsahu. I když zničíte K kopie zobrazení s N prvky, celková složitost je stále O(N) , protože základní rozsah je zničen pouze jednou.

Příklad: 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

Vytvořte zobrazení, které má stejný počáteční iterátor a typ sentinelu z rozsahu, který nemusí.

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

Parametry

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

  • views::all(rg) pokud rg je rozsah se stejným typem iterátoru a sentinelu.
  • common_view(views::all(rg)) pokud rg má různé typy iterátoru a sentinelu.

Poznámky

Pokud rozhraní API vyžaduje, aby počáteční iterátor a koncový sentinel měl stejný typ a zobrazení, které používáte, nesplňuje tento požadavek (nebo nevíte, jestli ano), použijte tento adaptér rozsahu common_viewk vytvoření . Zaručuje, že typ počátečního iterátoru a typu koncového sentinelu jsou stejné.

Příklad: 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

Vytvořte zobrazení prvních count prvků oblasti počínaje zadaným umístěním.

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

Parametry

DifferenceType
Typ počtu.

Iterator
Typ iterátoru.

count
Počet prvků, které se mají zahrnout do zobrazení. Musí být nezáporná.

  • Pokud count == 0se vrátí prázdná span hodnota.
  • Pokud count je větší než počet prvků v rozsahu, chování není definováno.

it
Iterátor prvku v oblasti, který má začínat. Prvek, na který iterátor odkazuje, je součástí vytvořeného zobrazení.

Vrácená hodnota

Vrátí span se, pokud it je contiguous_iterator pole, vektory a další kontejnery, které ukládají jejich prvky souvisle. subrange V opačném případě se vrátí hodnota.

Poznámky

Zahrnuté prvky jsou [it, count).

Po vytvoření zobrazení zůstane počet prvků v zobrazení stejný, i když byl rozsah, který byl vytvořen ze změn. Pokud se ale základní rozsah změní, může přístup k prvkům ze zobrazení způsobit nedefinované chování.

Příklad: 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

Vytvořte zobrazení, které vyloučí první n prvků oblasti.

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

Parametry

DifferenceType
Typ, který popisuje počet prvků, které se mají přeskočit.

count
Počet prvků, které se mají vyhodit z přední části rg. Musí být nezáporná.

  • Pokud count == 0se vrátí všechny prvky v rg .
  • Pokud count je větší než počet prvků v rg, vrátí se prázdné zobrazení.

R
Typ rozsahu.

rg
Oblast, která se používá k vytvoření zobrazení.

Vrácená hodnota

Zobrazení podkladového rozsahu se zadaným počtem prvků vynechaných zepředu.

Pokud zadáte více prvků, které mají být v podkladové oblasti empty_view , vrátí se.

Vrácené zobrazení je obvykle, ale ne vždy, specializace drop_view. To znamená:

Poznámky

Po vytvoření zůstane počet prvků v zobrazení stejný i v případě, že zobrazení, které bylo vytvořeno ze změn. Pokud se ale podkladové zobrazení změní, může přístup k prvkům ve vráceném zobrazení způsobit nedefinované chování.

drop je opakem take.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | drop(5). Nebo se dá použít se syntaxí volání funkce: drop(collection, 5) nebo drop(5)(collection).

Příklad: 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

Vytvořte zobrazení obsahující prvky oblasti, které zůstanou za úvodními prvky, které odpovídají zadané podmínce, se zahodí.

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

Parametry

R
Typ rozsahu.

predicate
Podmínky, které určují, které úvodní prvky se mají vypustit z rozsahu.

rg
Podkladová oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

A drop_while_view , který se skládá z prvků, které zůstávají, když jsou úvodní prvky, které odpovídají predikátu, vyřazeny.

Poznámky

Zastaví vyřazení prvků z rg jakmile predikát vrátí false.

drop_while je opakem take_while.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | drop_while(predicate). Nebo se dá použít se syntaxí volání funkce: drop_while(collection, predicate) nebo drop_while(predicate)(collection).

Příklad: 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

Vytvořte zobrazení elements_viewvybraného indexu do každé hodnoty podobné řazené kolekci členů v oblasti. Například vzhledem k rozsahu std::tuple<string, int> hodnot vytvořte elements_view ze všech prvků z každé řazené kolekce členů všechny string prvky.

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

Parametry

N
Index prvku, který chcete vybrat z každé hodnoty podobné řazené kolekci členů, která se má zahrnout do zobrazení.

R
Typ podkladové oblasti.

rg
Rozsah hodnot řazených kolekcí členů, ze které chcete vytvořit zobrazení.

Vrácená hodnota

Ten elements_view se skládá z vybraného indexu do každé hodnoty podobné řazené kolekci členů v kolekci.

Příklad: 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

Vytvořte zobrazení empty_view, které neobsahuje žádné prvky.

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

Parametry

T
Typ prvků v zobrazení. Zobrazení potřebuje typ elementu, i když neexistují žádné prvky.

Vrácená hodnota

A empty_view.

Poznámky

Může empty_view být užitečné při volání kódu, který vyžaduje zobrazení, ale nemusí zpracovávat žádné jeho prvky.

Příklad: 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

Vytvořte zobrazení obsahující prvky oblasti, které odpovídají zadané podmínce.

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

Parametry

P
Typ predikátu.

predicate
Podmínky, které určují, které prvky mají být v rozsahu zachovány.

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

A filter_view , který obsahuje prvky oblasti, které odpovídají predikátu.

Poznámky

Pro efektivitu, když používáte filter a transform společně s potrubím |, udělejte filter první, abyste transform pouze prvky, které chcete zachovat.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | filter(predicate). Nebo se dá použít se syntaxí volání funkce: filter(collection, predicate) nebo filter(predicate)(collection).

Příklad: 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

Vytvořte zobrazení, které obsahuje posloupnost rostoucích hodnot. Posloupnost může být ohraničena nebo ne.

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

Parametry

E
Typ koncové hodnoty.

S
Typ počáteční hodnoty.

startValue
První hodnota v sekvenci.

endValue
Tato hodnota je jedna za poslední hodnotou, která bude v sekvenci. Například std::views::iota(0, 5) vygeneruje zobrazení, které obsahuje hodnoty 0,1,2,3,4.

Vrácená hodnota

Posloupnost iota_view rostoucích hodnot.

Poznámky

U nevázané sekvence je chování po dosažení maximální hodnoty jeho datového typu nedefinované.

Příklad: 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

Vytvořte zobrazení nad prvky datového proudu.

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

Parametry

str
Objekt datového proudu. Jeho typ je odvozen od specializace std::basic_istream.

Val
Typ prvků, které se mají extrahovat z datového proudu.

Vrácená hodnota

Úloha basic_istream_view.

Tento adaptér rozsahu je ekvivalentní ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str), kde U je typ str.

Příklad: 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

Vytvořte zobrazení, které kombinuje všechny prvky více oblastí do jednoho zobrazení.

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

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

Parametry

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

A join_view , který obsahuje prvky všech oblastí v podkladové oblasti.

Příklad: 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.

Poznámky

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | join. Nebo se dá použít se syntaxí volání funkce: join(collection).

keys

Vytvořte keys_view první index do každé hodnoty podobné řazené kolekci členů v kolekci. To je užitečné pro extrakci klíčů z asociativních kontejnerů. Například vzhledem k rozsahu std::tuple<string, int>, vytvořit zobrazení, které se skládá ze všech string prvků z každé řazené kolekce členů.

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

Parametry

R
Typ podkladové oblasti.

Vrácená hodnota

Hodnota keys_view , která se skládá z prvního indexu do každé hodnoty podobné řazené kolekci členů v rozsahu.

Příklad: 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

Rozdělte rozsah na podranges na základě oddělovače. Oddělovač může být jeden prvek nebo zobrazení prvků.

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

Parametry

delimiter
Jedna hodnota nebo posloupnost hodnot, které určují, kam se má rozsah rozdělit.

Pattern
Typ oddělovače.

R
Typ rozsahu, který chcete rozdělit.

rg
Oblast, která se má rozdělit.

Vrácená hodnota

A lazy_split_view , který obsahuje jednu nebo více dílčích uspořádání a je výsledkem rozdělení původního rozsahu na delimiter.

Poznámky

Oddělovač není součástí výsledku. Pokud například rozdělíte rozsah 1,2,3 na hodnotu 2, získáte dvě dílčí uspořádání: 1 a 3.

Související adaptér je split. Mezi [split_view](split-view-class.md) and lazy_split_view' jsou hlavní rozdíly:

Zobrazení Může rozdělit oblast.const Iterátor rozsahu
split_view ne Podpora forward_range nebo vyšší
lazy_split_view ano input_range nebo vyšší

Preferujte split_view , protože je efektivnější, pokud není nutné rozdělit rozsah, který je const.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | lazy_split(delimiter). Nebo se dá použít se syntaxí volání funkce: lazy_split(collection, delimiter) nebo lazy_split(delimiter)(collection).

Příklad: 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

Umožňuje vytvořit zobrazení prvků oblasti v obráceném pořadí.

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

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

Parametry

R
Typ podkladové oblasti, která se má vrátit zpět.

rg
Oblast, která se má vrátit zpět.

Vrácená hodnota

Zobrazení, které představuje prvky podkladového rozsahu v obráceném pořadí. Vrácené zobrazení je obvykle, ale ne vždy, specializace reverse_view. To znamená:

  • Pokud V je specializace reverse_view, výsledkem je podkladové zobrazení argumentu. Dvojitá zpětná operace je operace typu no-op (žádná operace).
  • Pokud V má formulář subrange<reverse_iterator<I>, reverse_iterator<I>>, výsledek je subrange přepsaný iterátory. Dvojitý opak je no-op.
  • V opačném případě je reverse_viewvýsledkem .

Poznámky

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | reverse. Nebo se dá použít se syntaxí volání funkce: reverse(collection).

Příklad: 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

Vytvořte zobrazení single_view, které obsahuje jeden prvek.

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

Parametry

T
Typ prvku v zobrazení.

t
Hodnota elementu, který se má uložit v zobrazení.

Vrácená hodnota

tObsahuje single_view .

Poznámky

Toto zobrazení je užitečné pro testovací účely, pro volání kódu, který je potřeba poskytnout v zobrazení, které má alespoň jeden prvek v něm.

Příklad: 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

Rozdělte zobrazení na podranges na základě oddělovače. Oddělovač může být jeden prvek nebo posloupnost prvků.

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

Parametry

delimiter
Jedna hodnota nebo posloupnost hodnot, které určují, kam se má rozsah rozdělit.

Pattern
Typ oddělovače.

R
Typ podkladové oblasti, která se má rozdělit.

rg
Oblast, která se má rozdělit.

Vrácená hodnota

A split_view , která obsahuje nejméně jednu poduspořádku.

Poznámky

Oddělovač není součástí výsledku. Pokud například rozdělíte rozsah 1,2,3 na hodnotu 2, získáte dvě dílčí uspořádání: 1 a 3.

Související adaptér je lazy_split. Mezi hlavními rozdíly mezi split_view a lazy_split_view mezi těmito jednotlivými hodnotami jsou:

Zobrazení Může rozdělit oblast.const Typ rozsahu
split_view ne Podpora forward_range nebo vyšší
lazy_split_view ano Podpora input_range nebo vyšší

Preferujte split_view , protože je efektivnější, pokud není nutné rozdělit rozsah, který je const.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | split(delimiter). Nebo se dá použít se syntaxí volání funkce: split(collection, 5) nebo split(5)(collection).

Příklad: 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

Vytvořte zobrazení, které obsahuje zadaný počet prvků převzatých z přední části rozsahu.

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

Parametry

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

count
Početprvkůch rg

Vrácená hodnota

Vrácené zobrazení je obvykle, ale ne vždy, specializace take_view. Konkrétně:

Poznámky

Pokud zadáte více prvků, které se mají vzít, než existuje rg, budou odebrány všechny prvky.

take je opakem drop.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | take(5). Nebo se dá použít se syntaxí volání funkce: take(5, collection) nebo take(5)(collection).

Příklad: 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

Vytvořte zobrazení, které obsahuje úvodní prvky oblasti, které odpovídají zadané podmínce.

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

Parametry

P
Typ predikátu.

predicate
Podmínky, které určují, které úvodní prvky se mají zkopírovat z rozsahu.

R
Typ podkladové oblasti.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

A take_while_view , který se skládá z prvních count prvků, které splňují zadaná kritéria v oblasti.

Poznámky

Přestane po návratu false predikátu přebít prvky rg nebo oblast prvků vyprší.

take_while je opakem drop_while.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | take_while(pred). Nebo se dá použít se syntaxí volání funkce: take_while(collection, pred) nebo take_while(pred)(collection).

Příklad: 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

Vytvořte zobrazení prvků, z nichž každý je transformací prvku v zadaném rozsahu.

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

Parametry

F
Typ objektu funkce pro transformaci prvků.

R
Typ podkladové oblasti.

fun
Funkce, která transformuje prvky.

rg
Oblast, ze které chcete vytvořit zobrazení.

Vrácená hodnota

A transform_view , který obsahuje transformované prvky rg.

Poznámky

Z důvodu efektivity, když vytváříte filter a transform, udělejte filter první, abyste transform pouze prvky, které chcete zachovat.

Kód uvedený dříve jako "2)" lze použít se syntaxí svislé roury: collection | transform(fun). Nebo se dá použít se syntaxí volání funkce: transform(collection, fun) nebo transform(fun)(collection).

Příklad: 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

Vytvořte values_view , která se skládá z druhého indexu, do každé hodnoty podobné řazené kolekci členů v kolekci. To je užitečné pro zobrazení hodnot v asociativním kontejneru. Například s ohledem na rozsah std::tuple<string, int> hodnot vytvořte zobrazení, které se skládá ze všech int prvků z každé řazené kolekce členů.

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

Parametry

R
Typ podkladové oblasti.

rg
Základní rozsah hodnot řazených kolekcí členů.

Vrácená hodnota

Předdefinovaná values_view z druhého indexu do každé hodnoty podobné řazené kolekci členů v rozsahu.

Příklad: 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

Aliasy typu adaptéru rozsahu

all_t

Poskytuje typ zobrazení, které all vrací.

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

Parametry

R
Typ podkladové oblasti.

Vrácená hodnota

Typ zobrazení, který all vrací: decltype(views::all(std::declval<R>())).

Příklad: 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;
}

Viz také

<ranges>
<ranges> koncepty
Zobrazit třídy