Bagikan melalui


Adaptor rentang

Adaptor rentang membuat tampilan (salah satu kelas Tampilan di std::views namespace layanan) dari rentang. Kami menyarankan agar Anda menggunakan adaptor untuk membuat tampilan alih-alih membuat jenis tampilan secara langsung. Adaptor adalah cara yang dimaksudkan untuk mengakses tampilan. Mereka lebih mudah digunakan, dan dalam beberapa kasus lebih efisien, daripada membuat instans jenis tampilan secara langsung.

Tampilan adalah objek ringan yang mengacu pada elemen dari rentang. Tampilan dapat:

  • Hanya terdiri dari elemen tertentu dari rentang.
  • Mewakili transformasi elemen dari rentang.
  • Jadilah kebalikan dari, atau hanya elemen pertama n , rentang.
  • Jadilah kombinasi dari hal-hal sebelumnya.

Tampilan murah, O(1), untuk menyalin, menetapkan, dan menghancurkan - tidak peduli berapa banyak elemen yang terlibat. Pertimbangkan contoh berikut:

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

Adaptor rentang pertama, filter, menyediakan tampilan yang berisi elemen dari input yang dapat dibagi tiga. Adaptor rentang lainnya, transform, mengambil tampilan yang berisi elemen yang dapat dibagi tiga dan memberikan tampilan kuadrat dari elemen-elemen tersebut.

Saat adaptor rentang menghasilkan tampilan, adaptor rentang tidak dikenakan biaya untuk mengubah setiap elemen dalam rentang untuk menghasilkan tampilan tersebut. Biaya untuk memproses elemen dalam tampilan hanya dibayar saat Anda mengakses elemen tersebut.

Membuat tampilan adalah persiapan untuk melakukan pekerjaan di masa mendatang. Dalam contoh sebelumnya, membuat tampilan tidak mengakibatkan menemukan semua elemen yang dapat dibagi dengan tiga atau memadai elemen-elemen tersebut. Pekerjaan hanya terjadi saat Anda mengakses elemen dalam tampilan.

Elemen tampilan biasanya merupakan elemen aktual dari rentang yang digunakan untuk membuat tampilan. Tampilan biasanya tidak memiliki elemen; itu hanya mengacu pada mereka, dengan pengecualian owning_view. Mengubah elemen mengubah elemen tersebut dalam rentang tempat tampilan dibuat. Contoh berikut menunjukkan perilaku ini:

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

Adaptor rentang hadir dalam banyak bentuk. Misalnya, ada adaptor rentang yang memungkinkan Anda menghasilkan tampilan dengan:

  • Memfilter rentang lain berdasarkan predikat (filter).
  • Mengubah elemen dalam rentang (transform).
  • Memisahkan rentang (split).

Adaptor rentang dapat dirantai bersama -sama (terdiri). Di situlah daya dan fleksibilitas rentang paling jelas. Menyusun adaptor rentang memungkinkan Anda mengatasi masalah inti dengan algoritma Standard Template Library (STL) sebelumnya, yaitu tidak mudah untuk dirantai bersama.

Adaptor rentang berikut tersedia di std::views namespace layanan. Namespace std::views layanan adalah alias kenyamanan untuk std::ranges::views.

Adaptor rentang Deskripsi
allC++20 Buat tampilan yang mengacu pada rentang dan elemennya.
commonC++20 Buat tampilan yang memiliki jenis iterator dan sentinel yang sama dari rentang yang tidak.
countedC++20 Buat tampilan elemen n pertama dari rentang, dimulai dari lokasi yang ditentukan.
dropC++20 Buat tampilan dari tampilan lain, melewati jumlah elemen yang ditentukan dari depan.
drop_whileC++20 Buat tampilan yang berisi elemen rentang yang tersisa setelah elemen terkemuka yang cocok dengan kondisi yang ditentukan dihilangkan.
elementsC++20 Buat tampilan indeks yang dipilih ke dalam setiap nilai seperti tuple dalam rentang.
emptyC++20 Buat tampilan yang tidak memiliki elemen.
filterC++20 Buat tampilan yang berisi elemen rentang yang cocok dengan kondisi yang ditentukan.
iotaC++20 Buat tampilan yang berisi urutan peningkatan nilai.
istreamC++20 Buat tampilan di atas elemen aliran.
joinC++20 Buat tampilan yang menggabungkan semua elemen dari beberapa rentang ke dalam satu tampilan.
keysC++20 Buat tampilan indeks pertama ke dalam setiap nilai seperti tuple dalam koleksi.
lazy_splitC++20 Pisahkan tampilan menjadi subrang berdasarkan pemisah.
reverseC++20 Buat tampilan elemen rentang dalam urutan terbalik.
singleC++20 Buat tampilan yang berisi satu elemen.
splitC++20 Pisahkan tampilan menjadi subrang berdasarkan pemisah.
takeC++20 Buat tampilan elemen n pertama dari tampilan lain.
take_whileC++20 Buat tampilan yang berisi elemen utama rentang yang cocok dengan kondisi yang ditentukan.
transformC++20 Buat tampilan elemen yang diubah dari tampilan lain.
valuesC++20 Buat tampilan indeks kedua ke dalam setiap nilai seperti tuple dalam koleksi.

Dalam tabel sebelumnya, adaptor rentang biasanya dijelaskan sebagai mengambil rentang dan menghasilkan tampilan. Tepatnya, adaptor rentang memiliki argumen rentang yang menerima salah satu hal berikut:

  • Model cv-unqualifiedviewjenis , dan argumen adalah rvalue atau dapat disalin.
  • Ketika Anda meneruskan argumen sebagai lvalue, argumen harus memodelkan range dan hidup selama tampilan.
  • Ketika Anda meneruskan argumen sebagai rvalue, seperti saat memanggil , argumen harus range memodelkan owning_viewdan movable.

Fungsi adaptor rentang biasanya merupakan objek fungsi, yang terlihat seperti panggilan fungsi dan memberlakukan batasan pada jenis yang dapat diteruskan.

Anda dapat meneruskan adaptor rentang dan hasil operasi pipa (|) ke kode yang mengharapkan objek fungsi. Dalam contoh berikut, tampilan yang split dibuat adaptor rentang diteruskan ke transform adaptor rentang seolah-olah oleh panggilan fungsi, karena transform adaptor rentang adalah objek fungsi.

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

Buat tampilan semua elemen dalam rentang.

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

Parameter

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

  • Jika rg sudah menjadi tampilan, salinan rg.
  • Jika rg adalah lvalue non-tampilan, ref_view yang mengacu pada rg. (Masa pakai tampilan terikat dengan masa rgpakai .)
  • Jika rg adalah rvalue non-tampilan seperti objek sementara, atau merupakan hasil dari meneruskan rentang ke std::move, sebuah owning_view.

Gunakan std::views::all_t<decltype((rg))> untuk mendapatkan jenis tampilan yang dikembalikan.

Keterangan

Adaptor rentang ini adalah cara terbaik untuk mengonversi rentang menjadi tampilan. Salah satu alasan untuk membuat tampilan dari rentang adalah untuk meneruskannya berdasarkan nilai dengan biaya rendah, jika melewati rentang berdasarkan nilai bisa mahal.

Mendapatkan tampilan untuk rentang adalah alternatif yang berguna untuk melewati rentang kelas berat berdasarkan nilai karena tampilan murah untuk dibuat, disalin, dan dihancurkan. Pengecualian yang mungkin adalah owning_view, yang merupakan tampilan yang memiliki rentang yang mendasar.

Secara umum, skenario terburuk untuk menghancurkan tampilan memiliki O(N) kompleksitas untuk jumlah elemen dalam rentang. Bahkan jika Anda menghancurkan K salinan tampilan dengan N elemen, kompleksitas total masih O(N) karena rentang yang mendasar dihancurkan hanya sekali.

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

Buat tampilan yang memiliki iterator mulai dan jenis sentinel yang sama dari rentang yang mungkin tidak.

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

Parameter

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

  • views::all(rg) jika rg adalah rentang dengan iterator dan jenis sentinel yang sama.
  • common_view(views::all(rg)) jika rg memiliki jenis iterator dan sentinel yang berbeda.

Keterangan

Ketika API memerlukan iterator awal dan sentinel akhir untuk memiliki jenis yang sama, dan tampilan yang Anda gunakan tidak memenuhi persyaratan tersebut (atau Anda tidak tahu apakah itu terjadi), gunakan adaptor rentang ini untuk membuat common_view. Ini menjamin bahwa jenis iterator mulai dan jenis sentinel akhir sama.

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

Buat tampilan elemen pertama count rentang, dimulai dari lokasi yang ditentukan.

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

Parameter

DifferenceType
Jenis hitungan.

Iterator
Jenis iterator.

count
Jumlah elemen yang akan disertakan dalam tampilan. Harus non-negatif.

  • Jika count == 0, kosong span dikembalikan.
  • Jika count lebih besar dari jumlah elemen dalam rentang, perilaku tidak ditentukan.

it
Iterator ke elemen dalam rentang untuk memulai. Elemen yang dituju iterator disertakan dalam tampilan yang dibuat.

Nilai hasil

span dikembalikan jika it adalah contiguous_iterator untuk array, vektor, dan kontainer lain yang menyimpan elemennya secara berdekatan. Jika tidak, akan subrange dikembalikan.

Keterangan

Elemen yang disertakan adalah [it, count).

Setelah tampilan dibuat, jumlah elemen dalam tampilan tetap sama, bahkan jika rentang yang dibuat dari perubahan. Namun, jika rentang yang mendasar berubah, mengakses elemen dari tampilan dapat mengakibatkan perilaku yang tidak ditentukan.

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

Buat tampilan yang mengecualikan elemen n pertama dari rentang.

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

Parameter

DifferenceType
Jenis yang menjelaskan jumlah elemen yang akan dilewati.

count
Jumlah elemen yang akan dijatuhkan dari depan rg. Harus non-negatif.

  • Jika count == 0, semua elemen di rg dikembalikan.
  • Jika count lebih besar dari jumlah elemen dalam rg, tampilan kosong dikembalikan.

R
Jenis rentang.

rg
Rentang yang digunakan untuk membuat tampilan.

Nilai hasil

Tampilan rentang yang mendasar, dengan jumlah elemen yang ditentukan dihilangkan dari depan.

Jika Anda menentukan lebih banyak elemen untuk dihilangkan daripada yang ada dalam rentang yang mendasar, maka empty_view akan dikembalikan.

Tampilan yang dikembalikan biasanya, tetapi tidak selalu, spesialisasi dari drop_view. Yaitu:

Keterangan

Setelah dibuat, jumlah elemen dalam tampilan tetap sama meskipun tampilan dibuat dari perubahan. Namun, jika tampilan yang mendasar berubah, mengakses elemen dalam tampilan yang dikembalikan dapat mengakibatkan perilaku yang tidak ditentukan.

drop adalah kebalikan dari take.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | drop(5). Atau dapat digunakan dengan sintaks panggilan fungsi: drop(collection, 5) atau drop(5)(collection).

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

Buat tampilan yang berisi elemen rentang yang tersisa setelah elemen terkemuka yang cocok dengan kondisi yang ditentukan dihilangkan.

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

Parameter

R
Jenis rentang.

predicate
Kondisi yang menentukan elemen terkemuka mana yang akan dihilangkan dari rentang.

rg
Rentang yang mendasar untuk membuat tampilan.

Nilai hasil

drop_while_view yang terdiri dari elemen yang tetap ada ketika elemen terkemuka yang cocok dengan predikat dihilangkan.

Keterangan

Berhenti menghilangkan elemen segera rg setelah predikat mengembalikan false.

drop_while adalah kebalikan dari take_while.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | drop_while(predicate). Atau dapat digunakan dengan sintaks panggilan fungsi: drop_while(collection, predicate) atau drop_while(predicate)(collection).

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

elements_viewBuat , yang merupakan tampilan indeks yang dipilih ke dalam setiap nilai seperti tuple dalam rentang. Misalnya, mengingat rentang std::tuple<string, int> nilai, buat elements_view salah satu dari semua string elemen dari setiap tuple.

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

Parameter

N
Indeks elemen yang akan dipilih dari setiap nilai seperti tuple untuk disertakan dalam tampilan.

R
Jenis rentang yang mendasar.

rg
Rentang nilai seperti tuple untuk membuat tampilan.

Nilai hasil

Yang elements_view terdiri dari indeks yang dipilih ke dalam setiap nilai seperti tuple dalam koleksi.

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

empty_viewBuat , yang merupakan tampilan yang tidak memiliki elemen.

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

Parameter

T
Jenis elemen dalam tampilan. Tampilan membutuhkan jenis elemen, meskipun tidak ada elemen.

Nilai hasil

Sebuah empty_view.

Keterangan

empty_view Dapat berguna saat Anda memanggil kode yang memerlukan tampilan tetapi tidak perlu memproses salah satu elemennya.

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

Buat tampilan yang berisi elemen rentang yang cocok dengan kondisi yang ditentukan.

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

Parameter

P
Jenis predikat.

predicate
Kondisi yang menentukan elemen mana yang akan disimpan dalam rentang.

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

filter_view yang berisi elemen rentang yang cocok dengan predikat.

Keterangan

Demi efisiensi, ketika Anda menggunakan filter dan transform bersama dengan pipa |, lakukan yang filter pertama sehingga Anda transform hanya elemen yang ingin Anda simpan.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | filter(predicate). Atau dapat digunakan dengan sintaks panggilan fungsi: filter(collection, predicate) atau filter(predicate)(collection).

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

Buat tampilan yang berisi urutan peningkatan nilai. Urutan dapat dibatasi atau tidak.

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

Parameter

E
Jenis nilai akhir.

S
Jenis nilai awal.

startValue
Nilai pertama dalam urutan.

endValue
Nilai ini melewati nilai terakhir yang akan berada dalam urutan. Misalnya, std::views::iota(0, 5) menghasilkan tampilan yang memiliki nilai 0,1,2,3,4.

Nilai hasil

Urutan iota_view peningkatan nilai.

Keterangan

Untuk urutan yang tidak terbatas, perilaku tidak ditentukan setelah nilai maksimum jenis datanya tercapai.

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

Buat tampilan di atas elemen aliran.

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

Parameter

str
Objek streaming. Jenisnya berasal dari spesialisasi std::basic_istream.

Val
Jenis elemen yang akan diekstrak dari aliran.

Nilai hasil

basic_istream_view.

Adaptor rentang ini setara dengan ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str), di mana U adalah jenis str.

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

Buat tampilan yang menggabungkan semua elemen dari beberapa rentang ke dalam satu tampilan.

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

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

Parameter

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

yang join_view berisi elemen semua rentang dalam rentang yang mendasar.

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

Keterangan

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | join. Atau dapat digunakan dengan sintaks panggilan fungsi: join(collection).

keys

Buat keys_view indeks pertama ke dalam setiap nilai seperti tuple dalam koleksi. Ini berguna untuk mengekstrak kunci dari kontainer asosiatif. Misalnya, diberikan berbagai std::tuple<string, int>, buat tampilan yang terdiri dari semua string elemen dari setiap tuple.

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

Parameter

R
Jenis rentang yang mendasar.

Nilai hasil

keys_view yang terdiri dari indeks pertama ke dalam setiap nilai seperti tuple dalam rentang.

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

Pisahkan rentang menjadi subrang berdasarkan pemisah. Pemisah dapat menjadi elemen tunggal atau tampilan elemen.

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

Parameter

delimiter
Nilai tunggal, atau urutan nilai yang menentukan tempat untuk memisahkan rentang.

Pattern
Jenis pemisah.

R
Jenis rentang yang akan dipisahkan.

rg
Rentang untuk dipisahkan.

Nilai hasil

lazy_split_view yang berisi satu atau beberapa subranges dan merupakan hasil dari pemisahan rentang asli pada delimiter.

Keterangan

Pemisah bukan bagian dari hasil. Misalnya, jika Anda membagi rentang 1,2,3 pada nilai 2, Anda mendapatkan dua subrang: 1 dan 3.

Adaptor terkait adalah split. Perbedaan utama antara [split_view](split-view-class.md) and lazy_split_view' adalah:

Tampilkan Dapat memisahkan const rentang Perulang rentang
split_view no forward_range Mendukung atau lebih tinggi
lazy_split_view yes input_range atau lebih tinggi

Lebih suka split_view karena lebih efisien, kecuali Anda harus membagi rentang yaitu const.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | lazy_split(delimiter). Atau dapat digunakan dengan sintaks panggilan fungsi: lazy_split(collection, delimiter) atau lazy_split(delimiter)(collection).

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

Buat tampilan elemen rentang dalam urutan terbalik.

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

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

Parameter

R
Jenis rentang yang mendasar untuk membalikkan.

rg
Rentang untuk membalikkan.

Nilai hasil

Tampilan yang menyajikan elemen rentang yang mendasar dalam urutan terbalik. Tampilan yang dikembalikan biasanya, tetapi tidak selalu, spesialisasi dari reverse_view. Yaitu:

  • Jika V merupakan spesialisasi dari reverse_view, hasilnya adalah tampilan mendasar argumen. Double-reverse adalah no-op (tanpa operasi).
  • Jika V memiliki formulir subrange<reverse_iterator<I>, reverse_iterator<I>>, hasilnya adalah subrange dari iterator yang dibungkus. Double-reverse adalah no-op.
  • Jika tidak, hasilnya adalah reverse_view.

Keterangan

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | reverse. Atau dapat digunakan dengan sintaks panggilan fungsi: reverse(collection).

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

Buat single_view, yang merupakan tampilan yang berisi satu elemen.

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

Parameter

T
Jenis elemen dalam tampilan.

t
Nilai elemen yang akan disimpan dalam tampilan.

Nilai hasil

Yang single_view berisi t.

Keterangan

Tampilan ini berguna untuk tujuan pengujian, untuk kode panggilan yang perlu disediakan dengan tampilan yang memiliki setidaknya satu elemen di dalamnya.

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

Pisahkan tampilan menjadi subrang berdasarkan pemisah. Pemisah dapat menjadi elemen tunggal atau urutan elemen.

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

Parameter

delimiter
Nilai tunggal, atau urutan nilai yang menentukan tempat untuk memisahkan rentang.

Pattern
Jenis pemisah.

R
Jenis rentang yang mendasar untuk dipisahkan.

rg
Rentang untuk dipisahkan.

Nilai hasil

Yang split_view berisi satu atau beberapa subrang.

Keterangan

Pemisah bukan bagian dari hasil. Misalnya, jika Anda membagi rentang 1,2,3 pada nilai 2, Anda mendapatkan dua subrang: 1 dan 3.

Adaptor terkait adalah lazy_split. Perbedaan utama antara split_view dan lazy_split_view adalah:

Tampilkan Dapat memisahkan const rentang Jenis rentang
split_view no forward_range Mendukung atau lebih tinggi
lazy_split_view yes input_range Mendukung atau lebih tinggi

Lebih suka split_view karena lebih efisien, kecuali Anda harus membagi rentang yaitu const.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | split(delimiter). Atau dapat digunakan dengan sintaks panggilan fungsi: split(collection, 5) atau split(5)(collection).

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

Buat tampilan yang berisi jumlah elemen yang ditentukan yang diambil dari depan rentang.

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

Parameter

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

count
Jumlah elemen yang akan diambil dari depan rg.

Nilai hasil

Tampilan yang dikembalikan biasanya, tetapi tidak selalu, spesialisasi dari take_view. Khususnya:

Keterangan

Jika Anda menentukan lebih banyak elemen yang akan diambil daripada yang ada di rg, semua elemen diambil.

take adalah kebalikan dari drop.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | take(5). Atau dapat digunakan dengan sintaks panggilan fungsi: take(5, collection) atau take(5)(collection).

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

Buat tampilan yang berisi elemen utama rentang yang cocok dengan kondisi yang ditentukan.

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

Parameter

P
Jenis predikat.

predicate
Kondisi yang menentukan elemen terkemuka mana yang akan disalin dari rentang.

R
Jenis rentang yang mendasar.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

take_while_view yang terdiri dari elemen pertama count yang memenuhi kriteria yang ditentukan dalam rentang.

Keterangan

Berhenti mengambil elemen dari rg setelah predikat kembali false atau rentang kehabisan elemen.

take_while adalah kebalikan dari drop_while.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | take_while(pred). Atau dapat digunakan dengan sintaks panggilan fungsi: take_while(collection, pred) atau take_while(pred)(collection).

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

Buat tampilan elemen, yang masing-masing merupakan transformasi elemen dalam rentang yang ditentukan.

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

Parameter

F
Jenis objek fungsi untuk mengubah elemen.

R
Jenis rentang yang mendasar.

fun
Fungsi yang mengubah elemen.

rg
Rentang untuk membuat tampilan dari.

Nilai hasil

transform_view yang berisi elemen yang diubah dari rg.

Keterangan

Demi efisiensi, ketika Anda menyusun filter dan transform, lakukan yang filter pertama sehingga Anda transform hanya elemen yang ingin Anda simpan.

Kode yang ditampilkan sebelumnya sebagai "2)" dapat digunakan dengan sintaks pipa: collection | transform(fun). Atau dapat digunakan dengan sintaks panggilan fungsi: transform(collection, fun) atau transform(fun)(collection).

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

values_view Buat yang terdiri dari indeks kedua ke dalam setiap nilai seperti tuple dalam koleksi. Ini berguna untuk membuat tampilan nilai dalam kontainer asosiatif. Misalnya, mengingat rentang std::tuple<string, int> nilai, buat tampilan yang terdiri dari semua int elemen dari setiap tuple.

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

Parameter

R
Jenis rentang yang mendasar.

rg
Rentang nilai seperti tuple yang mendasar.

Nilai hasil

Dibangun values_view dari indeks kedua ke dalam setiap nilai seperti tuple dalam rentang.

Contoh: values

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    // ========== working with a map

    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Extract all of the years from the map
    for (int years : std::views::values(cpp_standards))
    {
        std::cout << years << ' '; // 2003 2011 2014 2017 1998 2020
    }
    std::cout << '\n';

    // ========== working with pairs

    std::vector<std::pair<std::string, int>> windows
    {
        {"Windows 1.0", 1985},
        {"Windows 2.0", 1987},
        {"Windows 3.0", 1990},
        {"Windows 3.1", 1992},
        {"Windows NT 3.1", 1993},
        {"Windows 95", 1995},
        {"Windows NT 4.0", 1996},
        {"Windows 95", 1995},
        {"Windows 98", 1998},
        {"Windows 1.0", 1985},
        {"Windows 2000", 2000}
    };

    // Another way to call the range adaptor by using '|'
    // Create a values_view that contains the year from each pair
    for (int years : windows | std::views::values)
    {
        std::cout << years << ' '; // 1985 1987 1990 1992 ...
    }
}
2003 2011 2014 2017 1998 2020
1985 1987 1990 1992 1993 1995 1996 1995 1998 1985 2000

Alias jenis adaptor rentang

all_t

Menyediakan jenis tampilan yang all ditampilkan.

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

Parameter

R
Jenis rentang yang mendasar.

Nilai hasil

Jenis tampilan yang all mengembalikan: decltype(views::all(std::declval<R>())).

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

Baca juga

<ranges>
<ranges> Konsep
Melihat kelas