Partilhar via


Adaptadores de gama

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 modos de exibição em vez de criar os tipos de exibição diretamente. Os adaptadores são a forma pretendida de aceder às vistas. 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.

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

  • Consistem em apenas determinados elementos de um intervalo.
  • Representar 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)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 filter intervalo, input, fornece uma visão que contém os elementos que são divisíveis por três. O outro adaptador de gama, transform, considera que contém os elementos divisíveis por três e fornece uma visão do quadrado desses elementos.

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

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

Os elementos de um modo de exibição geralmente são os elementos reais do intervalo usado para criar o modo de exibição. A exibiçã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 a partir do qual o modo de exibição foi criado. 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
    }
}

Os adaptadores de gama apresentam-se de muitas formas. Por exemplo, existem adaptadores de intervalo que permitem produzir uma visualização por:

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

Os adaptadores de gama podem ser encadeados (compostos). É aí que o poder e a flexibilidade das gamas são mais evidentes. Os adaptadores de intervalo de composição permitem 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 seguintes adaptadores de intervalo 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
all C++20 Crie um modo de exibição que se refira a um intervalo e seus elementos.
common C++20 Crie uma vista que tenha os mesmos tipos iterador e sentinela a partir de um intervalo que não tenha.
counted C++20 Crie uma exibição dos primeiros n elementos de um intervalo, começando pelo local especificado.
drop C++20 Crie uma vista a partir de outra vista, ignorando o número especificado de elementos da frente.
drop_while C++20 Crie um modo de exibição que contenha os elementos de um intervalo que permanecem depois que os elementos principais que correspondem à condição especificada são descartados.
elements C++20 Crie uma exibição do índice selecionado em cada valor semelhante a uma tupla em um intervalo.
empty C++20 Crie um modo de exibição que não tenha elementos.
filter C++20 Crie um modo de exibição que contenha os elementos de um intervalo que correspondam à condição especificada.
iota C++20 Crie um modo de exibição que contenha uma sequência de valores crescentes.
istream C++20 Crie uma exibição sobre os elementos de um fluxo.
join C++20 Crie um modo de exibição que combine todos os elementos de vários intervalos em um único modo de exibição.
keys C++20 Crie uma exibição do primeiro índice em cada valor semelhante a uma tupla em uma coleção.
lazy_split C++20 Divida uma vista em subintervalos com base num delimitador.
reverse C++20 Crie uma exibição dos elementos de um intervalo em ordem inversa.
single C++20 Crie um modo de exibição que contenha um elemento.
split C++20 Divida uma vista em subintervalos com base num delimitador.
take C++20 Crie uma vista dos primeiros n elementos a partir de outra vista.
take_while C++20 Crie um modo de exibição que contenha os elementos principais de um intervalo que correspondam à condição especificada.
transform C++20 Crie uma vista de elementos transformados a partir de outra vista.
values C++20 Crie uma exibição do segundo índice em cada valor semelhante a uma tupla em uma coleção.

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

  • Os cv-unqualified modelos viewde tipo , 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 são normalmente objetos de função, que se parecem com chamadas de função e impõem restrições aos 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 split adaptador de intervalo cria é passada para o transform adaptador de intervalo como se fosse por uma chamada de função, porque o transform adaptador de 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 a partir do qual criar a vista.

Valor de retorno

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

Use std::views::all_t<decltype((rg))> para obter o tipo do modo de exibição retornado.

Observações

Este adaptador de intervalo é a melhor maneira de converter um intervalo em uma exibição. Uma razão para criar uma visão a partir de um intervalo é passá-lo por valor a baixo custo, se passar o intervalo por valor pode ser caro.

Obter uma visualização para um intervalo é uma alternativa útil para passar um intervalo pesado por valor, porque as visualizaçõ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 que você destrua K cópias de 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 um modo de exibição que tenha o mesmo iterador inicial e o mesmo tipo de sentinela a partir 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 a partir do qual criar a vista.

Valor de retorno

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

Observações

Quando uma API exigir que o iterador inicial e o sentinela final tenham o mesmo tipo, e a exibição que você está usando não atender a esse requisito (ou você não sabe se atende), use esse adaptador de intervalo para criar um common_view. Garante que o tipo de iterador inicial e o tipo de sentinela final são os mesmos.

Exemplo: common

// requires /std:c++20 or later
#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 pelo 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 no modo de exibição. Deve ser não-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 de retorno

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

Observações

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

Depois que o modo de exibição é criado, o número de elementos no modo de exibição permanece o mesmo, mesmo que o intervalo a partir do qual ele foi criado seja alterado. No entanto, se o intervalo subjacente mudar, acessar elementos da exibição pode resultar em 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 um modo de 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 cair da frente do rg. Deve ser não-negativo.

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

R
O tipo do intervalo.

rg
O intervalo usado para criar o modo de exibição.

Valor de retorno

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

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

A exibição retornada é normalmente, mas nem sempre, uma especialização do drop_view. Isso é:

Observações

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

drop é o oposto de take.

O código mostrado anteriormente como "2)" pode ser usado com sintaxe 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 um modo de 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 cair do intervalo.

rg
O intervalo subjacente a partir do qual criar a vista.

Valor de retorno

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

Observações

Para de soltar elementos assim que o predicado rg retorna.false

drop_while é o oposto de take_while.

O código mostrado anteriormente como "2)" pode ser usado com sintaxe 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 a partir do qual criar a exibição.

Valor de retorno

Um elements_view que consiste no índice selecionado em cada valor semelhante a uma 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 é um modo de 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 de retorno

Um empty_view.

Observações

Um 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 later
#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 um modo de 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 a partir do qual criar a vista.

Valor de retorno

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

Observações

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

O código mostrado anteriormente como "2)" pode ser usado com sintaxe 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 um modo de 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
Este valor é um passado 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 de retorno

Um iota_view de uma sequência de valores crescentes.

Observações

Para uma sequência não limitada, 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 stream. Seu tipo é derivado de uma especialização de std::basic_istream.

Val
O tipo de elementos a extrair do fluxo.

Valor de retorno

Um 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 um modo de exibição que combine todos os elementos de vários intervalos em um único modo de 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 a partir do qual criar a vista.

Valor de retorno

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.

Observações

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

keys

Crie um keys_view do primeiro índice em cada valor semelhante a uma 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 de retorno

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 visã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 especifica onde dividir o intervalo.

Pattern
O tipo do delimitador.

R
O tipo de intervalo a dividir.

rg
O intervalo a dividir.

Valor de retorno

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

Observações

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 e lazy_split_view são:

Visualizar Pode dividir um const intervalo Iterador de alcance
split_view Não Suporta 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 sintaxe 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 em 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 de intervalo subjacente a reverter.

rg
O intervalo a inverter.

Valor de retorno

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

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

Observações

O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | reverse. Ou pode ser usado com 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 é um modo de 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 de retorno

Um single_view que contém t.

Observações

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 nele.

Exemplo: single

// requires /std:c++20 or later
#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 vista em subintervalos com base num 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 especifica onde dividir o intervalo.

Pattern
O tipo do delimitador.

R
O tipo do intervalo subjacente a dividir.

rg
O intervalo a dividir.

Valor de retorno

A split_view que contém um ou mais subintervalos.

Observações

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:

Visualizar Pode dividir um const intervalo Tipo de intervalo
split_view Não Suporta forward_range ou superior
lazy_split_view Sim Suporta 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 sintaxe 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 um modo de 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 a partir do qual criar a vista.

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

Valor de retorno

A exibição retornada é normalmente, mas nem sempre, uma especialização do take_view. Mais especificamente:

Observações

Se você especificar mais elementos a serem tomados do que os existentes no rg, todos os elementos serão usados.

take é o oposto de drop.

O código mostrado anteriormente como "2)" pode ser usado com sintaxe 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 um modo de 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 a partir do qual criar a vista.

Valor de retorno

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

Observações

Para de tomar elementos de rg 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 sintaxe 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 a partir do qual criar a vista.

Valor de retorno

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

Observações

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

O código mostrado anteriormente como "2)" pode ser usado com sintaxe 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 uma 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 consiste em todos os int elementos de cada tupla.

template <ranges::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 de retorno

Um 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 de tipo de 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 de retorno

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

Ver também

<ranges>
<ranges> conceitos
Ver aulas