Compartilhar via


Adaptadores de intervalo

Os adaptadores de intervalo criam uma exibição (uma das classes View no namespace) a std::views partir de um intervalo. Recomendamos que você use um adaptador para criar exibições em vez de criar os tipos de exibição diretamente. Os adaptadores são a maneira pretendida de acessar as exibições. Eles são mais fáceis de usar e, em alguns casos, mais eficientes do que criar instâncias dos tipos de exibição diretamente.

Uma exibição é um objeto leve que se refere a elementos de um intervalo. Uma exibição pode:

  • Consistem apenas em determinados elementos de um intervalo.
  • Representam uma transformação de elementos de um intervalo.
  • Seja o inverso ou apenas os primeiros n elementos de um intervalo.
  • Seja uma combinação das coisas anteriores.

Uma visão é barata, O(1)para copiar, atribuir e destruir - não importa quantos elementos estejam envolvidos. Considere o seguinte exemplo:

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

O primeiro adaptador de intervalo, filter, fornece uma exibição que contém os elementos que input são divisíveis por três. O outro adaptador de intervalo, transform, usa a exibição que contém os elementos divisíveis por três e fornece uma exibição do quadrado desses elementos.

Quando um adaptador de intervalo produz uma exibição, ele não incorre no custo de transformar todos os elementos no intervalo para produzir essa exibição. O custo para processar um elemento na exibição é pago somente quando você acessa esse elemento.

Criar uma exibição é uma preparação para fazer o trabalho no futuro. No exemplo anterior, a criação da vista não resulta na localização de todos os elementos divisíveis por três ou na elevabilidade desses elementos. O trabalho acontece somente quando você acessa um elemento na exibição.

Os elementos de uma exibição geralmente são os elementos reais do intervalo usado para criar a exibição. A visualização geralmente não possui os elementos; apenas se refere a eles, com exceção de owning_view. Alterar um elemento altera esse elemento no intervalo do qual a exibição foi criada. O exemplo a seguir mostra esse 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
    }
}

Adaptadores de intervalo vêm em várias formas. Por exemplo, existem adaptadores de intervalo que permitem que você produza uma exibição:

  • Filtrando outro intervalo com base em um predicado (filter).
  • Transformando os elementos em um intervalo (transform).
  • Dividindo um intervalo (split).

Os adaptadores de alcance podem ser encadeados (compostos). É aí que o poder e a flexibilidade dos intervalos são mais aparentes. A composição de adaptadores de intervalo permite que você supere um problema central com os algoritmos STL (Standard Template Library) anteriores, que é que eles não são fáceis de encadear.

Os adaptadores de intervalo a seguir estão disponíveis no std::views namespace. O std::views namespace é um alias de conveniência para std::ranges::views.

Adaptador de gama Descrição
allC++20 Crie uma exibição que se refira a um intervalo e seus elementos.
commonC++20 Crie uma exibição que tenha os mesmos tipos de iterador e sentinela de um intervalo que não tenha.
countedC++20 Crie uma exibição dos primeiros n elementos de um intervalo, começando pelo local especificado.
dropC++20 Crie uma vista a partir de outra vista, ignorando o número especificado de elementos da frente.
drop_whileC++20 Crie uma exibição que contenha os elementos de um intervalo que permanecem depois que os elementos principais que correspondem à condição especificada são descartados.
elementsC++20 Crie uma exibição do índice selecionado em cada valor semelhante a uma tupla em um intervalo.
emptyC++20 Crie uma vista que não tenha elementos.
filterC++20 Crie uma exibição que contenha os elementos de um intervalo que correspondam à condição especificada.
iotaC++20 Crie uma exibição que contenha uma sequência de valores crescentes.
istreamC++20 Crie uma exibição sobre os elementos de um fluxo.
joinC++20 Crie uma exibição que combine todos os elementos de vários intervalos em uma única exibição.
keysC++20 Crie uma exibição do primeiro índice em cada valor semelhante a tupla em uma coleção.
lazy_splitC++20 Divida uma exibição em subintervalos com base em um delimitador.
reverseC++20 Crie uma exibição dos elementos de um intervalo na ordem inversa.
singleC++20 Crie uma exibição que contenha um elemento.
splitC++20 Divida uma exibição em subintervalos com base em um delimitador.
takeC++20 Crie uma visualização dos primeiros n elementos de outra visualização.
take_whileC++20 Crie uma exibição que contenha os elementos principais de um intervalo que correspondam à condição especificada.
transformC++20 Crie uma vista de elementos transformados a partir de outra vista.
valuesC++20 Crie uma exibição do segundo índice em cada valor semelhante a tupla em uma coleção.

Na tabela anterior, um adaptador de intervalo é normalmente descrito como pegando um intervalo e produzindo uma exibição. Para ser preciso, os adaptadores de intervalo têm um argumento de intervalo que aceita um dos seguintes:

  • O cv-unqualified tipo modela view, e o argumento é um rvalue ou é copiável.
  • Quando você passa o argumento como um lvalue, ele deve modelar range e viver tanto quanto a exibição.
  • Quando você passa o argumento como um rvalue, como ao chamar owning_view, ele deve modelar range e movable.

As funções do adaptador de intervalo normalmente são objetos de função, que se parecem com chamadas de função e impõem restrições nos tipos que podem ser passados.

Você pode passar adaptadores de intervalo e o resultado de operações de pipe (|) para o código que espera objetos de função. No exemplo a seguir, a exibição que o adaptador de split intervalo cria é passada para o transform adaptador de intervalo como se fosse por uma chamada de função, pois o adaptador de transform intervalo é um objeto de função.

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

Crie uma exibição de todos os elementos em um intervalo.

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

Parâmetros

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

Valor retornado

  • Se rg já for uma exibição, uma cópia do rg.
  • Se rg for um lvalue sem visualização, a ref_view que se refere a rg. (O tempo de vida da exibição está vinculado ao tempo de vida de rg.)
  • If rg é um rvalue que não é de exibição, como um objeto temporário, ou é o resultado da passagem do intervalo para std::move, um owning_view.

Use std::views::all_t<decltype((rg))> para obter o tipo da exibição retornada.

Comentários

Esse adaptador de intervalo é a melhor maneira de converter um intervalo em uma exibição. Um motivo para criar uma exibição de um intervalo é passá-la por valor a baixo custo, se passar o intervalo por valor puder ser caro.

Obter uma exibição para um intervalo é uma alternativa útil para passar um intervalo de peso pesado por valor porque as exibições são baratas para criar, copiar e destruir. Uma possível exceção é owning_view, que é uma exibição que possui o intervalo subjacente.

Em geral, o pior cenário para destruir uma exibição tem O(N) complexidade para o número de elementos no intervalo. Mesmo se você destruir K cópias da exibição com N elementos, a complexidade total ainda O(N) é porque o intervalo subjacente é destruído apenas uma vez.

Exemplo: 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

Crie uma exibição que tenha o mesmo iterador inicial e tipo sentinela de um intervalo que talvez não tenha.

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

Parâmetros

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

Valor retornado

  • views::all(rg) if rg é um intervalo com o mesmo tipo de iterador e sentinela.
  • common_view(views::all(rg)) if rg tem diferentes tipos de iterador e sentinela.

Comentários

Quando uma API exige que o iterador begin e o sentinel end tenham o mesmo tipo e a exibição que você está usando não atende a esse requisito (ou você não sabe se atende), use esse adaptador de intervalo para criar um common_view. Ele garante que o tipo do iterador de início e o tipo do sentinela final sejam os mesmos.

Exemplo: 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

Crie uma exibição dos primeiros count elementos de um intervalo, começando no local especificado.

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

Parâmetros

DifferenceType
O tipo da contagem.

Iterator
O tipo do iterador.

count
O número de elementos a serem incluídos na exibição. Não deve ser negativo.

  • Se count == 0, um vazio span é retornado.
  • Se count for maior que o número de elementos no intervalo, o comportamento será indefinido.

it
Um iterador para o elemento no intervalo para começar. O elemento para o qual o iterador aponta é incluído na exibição criada.

Valor retornado

A span é retornado se it for a contiguous_iterator para matrizes, vetores e outros contêineres que armazenam seus elementos de forma contígua. Caso contrário, a subrange será retornado.

Comentários

Os elementos incluídos são [it, count).

Depois que a exibição é criada, o número de elementos na exibição permanece o mesmo, mesmo que o intervalo do qual ela foi criada seja alterado. No entanto, se o intervalo subjacente for alterado, o acesso a elementos da exibição poderá resultar em um comportamento indefinido.

Exemplo: 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

Crie uma exibição que exclua os primeiros n elementos de um intervalo.

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

Parâmetros

DifferenceType
O tipo que descreve o número de elementos a serem ignorados.

count
O número de elementos a serem descartados da frente do rg. Não deve ser negativo.

  • Se count == 0, todos os elementos em rg são retornados.
  • Se count for maior que o número de elementos em rg, uma exibição vazia será retornada.

R
O tipo do intervalo.

rg
O intervalo usado para criar a exibição.

Valor retornado

Uma exibição do intervalo subjacente, com o número especificado de elementos descartados da frente.

Se você especificar mais elementos a serem descartados do que existem no intervalo subjacente, an empty_view será retornado.

A exibição retornada é normalmente, mas nem sempre, uma especialização de drop_view. Ou seja:

Comentários

Depois de criado, o número de elementos na exibição permanece o mesmo, mesmo que a exibição da qual ele foi criado seja alterada. No entanto, se a exibição subjacente for alterada, o acesso a elementos na exibição retornada poderá resultar em um comportamento indefinido.

drop é o oposto de take.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | drop(5). Ou pode ser usado com sintaxe de chamada de função: drop(collection, 5) ou drop(5)(collection).

Exemplo: 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

Crie uma exibição que contenha os elementos de um intervalo que permanecem depois que os elementos principais que correspondem à condição especificada são descartados.

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

Parâmetros

R
O tipo do intervalo.

predicate
As condições que determinam quais elementos principais devem ser descartados do intervalo.

rg
O intervalo subjacente do qual criar a exibição.

Valor retornado

A drop_while_view que consiste nos elementos que permanecem quando os elementos principais que correspondem ao predicado são descartados.

Comentários

Interrompe o descarte de rg elementos assim que o predicado retorna false.

drop_while é o oposto de take_while.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | drop_while(predicate). Ou pode ser usado com sintaxe de chamada de função: drop_while(collection, predicate) ou drop_while(predicate)(collection).

Exemplo: 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

Crie um elements_view, que é uma exibição do índice selecionado em cada valor semelhante a uma tupla em um intervalo. Por exemplo, dado um intervalo de std::tuple<string, int> valores, crie um elements_view de todos os string elementos de cada tupla.

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

Parâmetros

N
O índice do elemento a ser selecionado de cada valor semelhante a uma tupla a ser incluído na exibição.

R
O tipo do intervalo subjacente.

rg
O intervalo de valores semelhantes a tuplas para criar a exibição.

Valor retornado

Um elements_view que consiste no índice selecionado em cada valor semelhante a tupla em uma coleção.

Exemplo: 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

Crie um empty_view, que é uma exibição que não tem elementos.

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

Parâmetros

T
O tipo dos elementos na exibição. A exibição precisa de um tipo de elemento, mesmo que não haja elementos.

Valor retornado

Um empty_view.

Comentários

An empty_view pode ser útil quando você está chamando um código que requer uma exibição, mas não precisa processar nenhum de seus elementos.

Exemplo: 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

Crie uma exibição que contenha os elementos de um intervalo que correspondam à condição especificada.

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

Parâmetros

P
O tipo do predicado.

predicate
As condições que determinam quais elementos manter no intervalo.

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

Valor retornado

A filter_view que contém os elementos de um intervalo que correspondem ao predicado.

Comentários

Por uma questão de eficiência, quando você usar filter e transform junto com um tubo |, faça o filter primeiro para que você transform apenas os elementos que pretende manter.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | filter(predicate). Ou pode ser usado com sintaxe de chamada de função: filter(collection, predicate) ou filter(predicate)(collection).

Exemplo: 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

Crie uma exibição que contenha uma sequência de valores crescentes. A sequência pode ser limitada ou não.

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

Parâmetros

E
O tipo do valor final.

S
O tipo do valor inicial.

startValue
O primeiro valor na sequência.

endValue
Esse valor é um após o último valor que estará na sequência. Por exemplo, std::views::iota(0, 5) gera uma exibição que tem os valores 0,1,2,3,4.

Valor retornado

Um iota_view de uma sequência de valores crescentes.

Comentários

Para uma sequência não associada, o comportamento é indefinido depois que o valor máximo de seu tipo de dados é atingido.

Exemplo: 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

Crie uma exibição sobre os elementos de um fluxo.

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

Parâmetros

str
Um objeto de fluxo. Seu tipo é derivado de uma especialização de std::basic_istream.

Val
O tipo dos elementos a serem extraídos do fluxo.

Valor retornado

Uma basic_istream_view.

Este adaptador de intervalo é equivalente a ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str), onde U é o tipo de str.

Exemplo: 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

Crie uma exibição que combine todos os elementos de vários intervalos em uma única exibição.

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

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

Parâmetros

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

Valor retornado

A join_view que contém os elementos de todos os intervalos no intervalo subjacente.

Exemplo: 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.

Comentários

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | join. Ou pode ser usado com a sintaxe de chamada de função: join(collection).

keys

Crie um keys_view do primeiro índice em cada valor semelhante a tupla em uma coleção. Isso é útil para extrair chaves de contêineres associativos. Por exemplo, dado um intervalo de std::tuple<string, int>, crie uma exibição que consiste em todos os string elementos de cada tupla.

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

Parâmetros

R
O tipo do intervalo subjacente.

Valor retornado

A keys_view que consiste no primeiro índice em cada valor semelhante a uma tupla no intervalo.

Exemplo: 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

Divida um intervalo em subintervalos com base em um delimitador. O delimitador pode ser um único elemento ou uma visualização de elementos.

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

Parâmetros

delimiter
Um único valor ou uma sequência de valores que especificam onde dividir o intervalo.

Pattern
O tipo do delimitador.

R
O tipo do intervalo a ser dividido.

rg
O intervalo a ser dividido.

Valor retornado

A lazy_split_view que contém um ou mais subintervalos e é o resultado da divisão do intervalo original em delimiter.

Comentários

O delimitador não faz parte do resultado. Por exemplo, se você dividir o intervalo 1,2,3 no valor 2, obterá dois subintervalos: 1 e 3.

Um adaptador relacionado é split. As principais diferenças entre [split_view](split-view-class.md) and lazy_split_view' são:

Exibir Pode dividir um const intervalo Iterador de intervalo
split_view não Suportes forward_range ou superior
lazy_split_view sim input_range ou superior

Prefira split_view porque é mais eficiente, a menos que você precise dividir um intervalo que seja const.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | lazy_split(delimiter). Ou pode ser usado com sintaxe de chamada de função: lazy_split(collection, delimiter) ou lazy_split(delimiter)(collection).

Exemplo: 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

Crie uma exibição dos elementos de um intervalo na ordem inversa.

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

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

Parâmetros

R
O tipo do intervalo subjacente a ser revertido.

rg
O intervalo a ser revertido.

Valor retornado

Uma exibição que apresenta os elementos do intervalo subjacente em ordem inversa. A exibição retornada é normalmente, mas nem sempre, uma especialização de reverse_view. Ou seja:

  • Se V é uma especialização de reverse_view, o resultado é a visão subjacente do argumento. Um reverso duplo é um no-op (sem operação).
  • Se V tiver o formulário subrange<reverse_iterator<I>, reverse_iterator<I>>, o resultado é um subrange dos iteradores desencapsulados. Um duplo reverso é um no-op.
  • Caso contrário, o resultado será reverse_view.

Comentários

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | reverse. Ou pode ser usado com a sintaxe de chamada de função: reverse(collection).

Exemplo: 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

Crie um single_view, que é uma exibição que contém um elemento.

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

Parâmetros

T
O tipo do elemento na exibição.

t
O valor do elemento a ser armazenado na exibição.

Valor retornado

Um single_view que contém t.

Comentários

Essa exibição é útil para fins de teste, para chamar o código que precisa ser fornecido com uma exibição que tenha pelo menos um elemento.

Exemplo: 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

Divida uma exibição em subintervalos com base em um delimitador. O delimitador pode ser um único elemento ou uma sequência de elementos.

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

Parâmetros

delimiter
Um único valor ou uma sequência de valores que especificam onde dividir o intervalo.

Pattern
O tipo do delimitador.

R
O tipo do intervalo subjacente a ser dividido.

rg
O intervalo a ser dividido.

Valor retornado

A split_view que contém um ou mais subintervalos.

Comentários

O delimitador não faz parte do resultado. Por exemplo, se você dividir o intervalo 1,2,3 no valor 2, obterá dois subintervalos: 1 e 3.

Um adaptador relacionado é lazy_split. As principais diferenças entre split_view e lazy_split_view são:

Exibir Pode dividir um const intervalo Tipo de intervalo
split_view não Suportes forward_range ou superior
lazy_split_view sim Suportes input_range ou superior

Prefira split_view porque é mais eficiente, a menos que você precise dividir um intervalo que seja const.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | split(delimiter). Ou pode ser usado com sintaxe de chamada de função: split(collection, 5) ou split(5)(collection).

Exemplo: 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

Crie uma exibição que contenha o número especificado de elementos retirados da frente de um intervalo.

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

Parâmetros

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

count
O número de elementos a serem retirados da frente do rg.

Valor retornado

A exibição retornada é normalmente, mas nem sempre, uma especialização de take_view. Especificamente:

Comentários

Se você especificar mais elementos a serem obtidos do que existem no rg, todos os elementos serão obtidos.

take é o oposto de drop.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | take(5). Ou pode ser usado com sintaxe de chamada de função: take(5, collection) ou take(5)(collection).

Exemplo: 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

Crie uma exibição que contenha os elementos principais de um intervalo que correspondam à condição especificada.

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

Parâmetros

P
O tipo do predicado.

predicate
As condições que determinam quais elementos principais copiar do intervalo.

R
O tipo do intervalo subjacente.

rg
O intervalo do qual criar a exibição.

Valor retornado

A take_while_view que consiste nos primeiros count elementos que atendem aos critérios especificados no intervalo.

Comentários

Interrompe a obtenção de rg elementos depois que o predicado retorna false ou o intervalo fica sem elementos.

take_while é o oposto de drop_while.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | take_while(pred). Ou pode ser usado com sintaxe de chamada de função: take_while(collection, pred) ou take_while(pred)(collection).

Exemplo: 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

Crie uma exibição de elementos, cada um dos quais é uma transformação de um elemento no intervalo especificado.

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

Parâmetros

F
O tipo do objeto de função para transformar os elementos.

R
O tipo do intervalo subjacente.

fun
A função que transforma os elementos.

rg
O intervalo do qual criar a exibição.

Valor retornado

A transform_view que contém os elementos transformados de rg.

Comentários

Por uma questão de eficiência, quando você compõe filter e transform, faça o filter primeiro para que você transform apenas os elementos que pretende manter.

O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | transform(fun). Ou pode ser usado com sintaxe de chamada de função: transform(collection, fun) ou transform(fun)(collection).

Exemplo: 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

Crie um values_view que consiste no segundo índice em cada valor semelhante a tupla em uma coleção. Isso é útil para fazer uma exibição dos valores em um contêiner associativo. Por exemplo, dado um intervalo de std::tuple<string, int> valores, crie uma exibição que consista em todos os int elementos de cada tupla.

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

Parâmetros

R
O tipo do intervalo subjacente.

rg
O intervalo subjacente de valores semelhantes a tuplas.

Valor retornado

A values_view construído a partir do segundo índice em cada valor semelhante a uma tupla no intervalo.

Exemplo: 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

Aliases do tipo adaptador de intervalo

all_t

Fornece o tipo de exibição que all retorna.

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

Parâmetros

R
O tipo do intervalo subjacente.

Valor retornado

O tipo de exibição que all retorna: decltype(views::all(std::declval<R>())).

Exemplo: 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;
}

Confira também

<ranges>
<ranges> Conceitos
Ver aulas