次の方法で共有


範囲アダプター

範囲アダプターは、範囲から view ( View クラスの 1 つ std::views 名前空間内) を作成します。 ビューの種類を直接作成するのではなく、アダプターを使用してビューを作成することをお勧めします。 アダプターは、ビューにアクセスするための目的の方法です。 ビューの種類のインスタンスを直接作成するよりも、使いやすく、効率的な場合もあります。

ビューは、範囲の要素を参照する軽量オブジェクトです。 ビューは次のことができます。

  • 範囲の特定の要素のみで構成されます。
  • 範囲からの要素の変換を表します。
  • 範囲の最初の n 要素の逆または唯一の要素である。
  • 上記の組み合わせにする。

ビューは、関係する要素の数に関係なく、コピー、割り当て、破棄を行う安価で O(1)です。 次の例を確認してください。

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

最初の範囲アダプター filterは、3 つ割り切れる input の要素を含むビューを提供します。 もう 1 つの範囲アダプター transformは、3 で割り切れる要素を含むビューを受け取り、それらの要素の正方形のビューを提供します。

範囲アダプターがビューを生成しても、そのビューを生成するために範囲内のすべての要素を変換するコストは発生しません。 ビュー内の要素を処理するためのコストは、その要素にアクセスした場合にのみ支払われます。

ビューの作成は、将来の作業を行う準備です。 前の例では、ビューを作成しても、3 つの要素で割り切れるすべての要素が検索されたり、それらの要素が 2 乗されたりすることはありません。 作業は、ビュー内の要素にアクセスする場合にのみ行われます。

通常、ビューの要素は、ビューの作成に使用される範囲の実際の要素です。 通常、ビューは要素を所有していません。 owning_viewを除き、それらを参照するだけです。 要素を変更すると、ビューの作成元の範囲内の要素が変更されます。 次の例は、この動作を示しています。

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

範囲アダプターは多くの形式で提供されます。 たとえば、次の方法でビューを生成できる範囲アダプターがあります。

  • 述語 (filter) に基づいて別の範囲をフィルター処理する。
  • 範囲内の要素の変換 (transform)。
  • 範囲の分割 (split)。

範囲アダプターは、連結 (構成) できます。 そこで、範囲のパワーと柔軟性が最も明らかになります。 範囲アダプターを作成すると、以前の標準テンプレート ライブラリ (STL) アルゴリズムの主要な問題を克服できます。これは、これらのアルゴリズムを連結するのは簡単ではありません。

std::views名前空間では、次の範囲アダプターを使用できます。 std::views名前空間は、std::ranges::viewsの便利なエイリアスです。

範囲アダプター 説明
allC++20 範囲とその要素を参照するビューを作成します。
commonC++20 ない範囲から同じ反復子とセンチネル型を持つビューを作成します。
countedC++20 指定した位置から始まる範囲の最初の n 要素のビューを作成します。
dropC++20 別のビューからビューを作成し、指定した数の要素を前面からスキップします。
drop_whileC++20 指定した条件に一致する先頭の要素が削除された後に残る範囲の要素を含むビューを作成します。
elementsC++20 範囲内の各タプルに似た値に、選択したインデックスのビューを作成します。
emptyC++20 要素のないビューを作成します。
filterC++20 指定した条件に一致する範囲の要素を含むビューを作成します。
iotaC++20 増加する値のシーケンスを含むビューを作成します。
istreamC++20 ストリームの要素に対してビューを作成します。
joinC++20 複数の範囲のすべての要素を 1 つのビューに結合するビューを作成します。
keysC++20 コレクション内の各タプルに似た値に最初のインデックスのビューを作成します。
lazy_splitC++20 区切り記号に基づいてビューをサブ範囲に分割します。
reverseC++20 範囲の要素のビューを逆の順序で作成します。
singleC++20 1 つの要素を含むビューを作成します。
splitC++20 区切り記号に基づいてビューをサブ範囲に分割します。
takeC++20 別のビューから最初の n 要素のビューを作成します。
take_whileC++20 指定した条件に一致する範囲の先頭要素を含むビューを作成します。
transformC++20 変換された要素のビューを別のビューから作成します。
valuesC++20 コレクション内の各タプルに似た値に、2 番目のインデックスのビューを作成します。

前の表では、範囲アダプターは通常、範囲を取得してビューを生成すると説明されています。 正確には、範囲アダプターには、次のいずれかを受け入れる範囲引数があります。

  • cv-unqualified型モデルview。引数は右辺値であるか、コピー可能です。
  • 左辺値として引数を渡す場合は、ビューに限り、 range モデル化され、ライブである必要があります。
  • 引数を右辺値として渡す場合 ( owning_viewを呼び出す場合など)、 rangemovableをモデル化する必要があります。

範囲アダプター関数は、通常、関数呼び出しのように見え渡すことができる型に制約を適用する関数オブジェクトです。

範囲アダプターとパイプ操作の結果 (|) を、関数オブジェクトを必要とするコードに渡すことができます。 次の例では、transform範囲アダプターが関数オブジェクトであるため、split範囲アダプターが作成したビューは、関数呼び出しのようにtransform範囲アダプターに渡されます。

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

範囲内のすべての要素のビューを作成します。

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

パラメーター

R
基になる範囲の型。

rg
ビューを作成する範囲。

戻り値

  • rgが既にビューである場合は、rgのコピー。
  • rgがビュー以外の左辺値の場合は、rgを参照するref_view。 (ビューの有効期間は、 rgの有効期間に関連付けられています)。
  • rgが一時オブジェクトなどのビュー以外の右辺値である場合、または範囲をstd::moveに渡した結果である場合は、owning_view

std::views::all_t<decltype((rg))>を使用して、返されるビューの型を取得します。

解説

この範囲アダプターは、範囲をビューに変換する最適な方法です。 範囲からビューを作成する理由の 1 つは、値渡しのコストが高くなる可能性がある範囲を低コストで渡すことです。

ビューの作成、コピー、破棄は低コストであるため、範囲のビューを取得することは、重み付け範囲を値渡しする代わりに便利です。 考えられる例外は、基になる範囲を所有するビューである owning_viewです。

一般に、ビューを破棄する最悪のシナリオでは、範囲内の要素の数 O(N) 複雑になります。 N要素Kビューのコピーを破棄した場合でも、基になる範囲は 1 回だけ破棄されるため、全体の複雑さがO(N)

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

ない範囲から、同じ開始反復子と sentinel 型を持つビューを作成します。

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

パラメーター

R
基になる範囲の型。

rg
ビューを作成する範囲。

戻り値

  • views::all(rg)rgが同じ反復子と sentinel 型の範囲である場合。
  • common_view(views::all(rg))rgの反復子とセンチネルの型が異なる場合は。

解説

API で開始反復子と終了センチネルの型が同じである必要があり、使用しているビューがその要件を満たしていない (または満たしていない場合) 場合は、この範囲アダプターを使用して common_viewを作成します。 開始反復子の型と終了 sentinel の型が同じであることを保証します。

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

指定した位置から始まる範囲の最初の count 要素のビューを作成します。

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

パラメーター

DifferenceType
カウントの型。

Iterator
反復子の型。

count
ビューに含める要素の数。 負以外にする必要があります。

  • count == 0場合は、空のspanが返されます。
  • countが範囲内の要素の数より大きい場合、動作は未定義です。

it
開始する範囲内の要素を指す反復子。 反復子が指す要素は、作成されたビューに含まれます。

戻り値

itが、要素を連続して格納する配列、ベクター、およびその他のコンテナーのcontiguous_iteratorである場合、spanが返されます。 それ以外の場合は、 subrange が返されます。

解説

含まれる要素は [it, count)

ビューが作成された後、ビュー内の要素の数は、変更から作成された範囲であっても同じままです。 ただし、基になる範囲が変更された場合、ビューから要素にアクセスすると、未定義の動作が発生する可能性があります。

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

範囲の最初の n 要素を除外するビューを作成します。

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

パラメーター

DifferenceType
スキップする要素の数を表す型。

count
rgの前面から削除する要素の数。 負以外にする必要があります。

  • count == 0場合は、rg内のすべての要素が返されます。
  • countrg内の要素の数より大きい場合は、空のビューが返されます。

R
範囲の型。

rg
ビューの作成に使用される範囲。

戻り値

指定した数の要素が前面から削除された基になる範囲のビュー。

ドロップする要素の数が基になる範囲よりも多い場合は、 empty_view が返されます。

返されるビューは通常、 drop_viewの特殊化であるとは限りません。 つまり、

解説

作成後、ビュー内の要素の数は、ビューが変更から作成された場合でも同じままです。 ただし、基になるビューが変更された場合、返されるビュー内の要素にアクセスすると、未定義の動作が発生する可能性があります。

droptakeの反対です。

前に "2)" として示したコードは、パイプ構文 ( collection | drop(5)) と共に使用できます。 または、関数呼び出し構文 ( drop(collection, 5) または drop(5)(collection)) と共に使用することもできます。

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

指定した条件に一致する先頭の要素が削除された後に残る範囲の要素を含むビューを作成します。

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

パラメーター

R
範囲の型。

predicate
範囲からドロップする先頭要素を決定する条件。

rg
ビューを作成する基になる範囲。

戻り値

述語に一致する先頭の要素が削除されたときに残る要素で構成される drop_while_view

解説

述語からfalseが返されるとすぐに、rgからの要素の削除を停止します。

drop_whiletake_whileの反対です。

前に "2)" として示したコードは、パイプ構文 ( collection | drop_while(predicate)) と共に使用できます。 または、関数呼び出し構文 ( drop_while(collection, predicate) または drop_while(predicate)(collection)) と共に使用することもできます。

例: 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_viewを作成します。これは、範囲内の各タプルに似た値に、選択したインデックスのビューです。 たとえば、std::tuple<string, int>値の範囲がある場合は、各タプルからすべてのstring要素のelements_viewを作成します。

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

パラメーター

N
ビューに含めるタプルに似た値から選択する要素のインデックス。

R
基になる範囲の型。

rg
ビューを作成するタプルに似た値の範囲。

戻り値

コレクション内の各タプルに似た値に、選択したインデックスで構成される elements_view

例: 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_viewを作成します。

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

パラメーター

T
ビュー内の要素の型。 要素がない場合でも、ビューには要素型が必要です。

戻り値

empty_view

解説

empty_viewは、ビューを必要とするが、その要素を処理する必要がないコードを呼び出す場合に役立ちます。

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

指定した条件に一致する範囲の要素を含むビューを作成します。

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

パラメーター

P
述語の型。

predicate
範囲内に保持する要素を決定する条件。

R
基になる範囲の型。

rg
ビューを作成する範囲。

戻り値

述語と一致する範囲の要素を含む filter_view

解説

効率を高めるために、 filtertransform をパイプ |と一緒に使用する場合は、最初に filter を実行して、保持する要素のみを transform します。

前に "2)" として示したコードは、パイプ構文 ( collection | filter(predicate)) と共に使用できます。 または、関数呼び出し構文 ( filter(collection, predicate) または filter(predicate)(collection)) と共に使用することもできます。

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

増加する値のシーケンスを含むビューを作成します。 シーケンスは境界付けすることもできません。

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

パラメーター

E
終了値の型。

S
開始値の型。

startValue
シーケンス内の最初の値。

endValue
この値は、シーケンス内の最後の値の 1 つ後にあります。 たとえば、 std::views::iota(0, 5) は、 0,1,2,3,4値を持つビューを生成します。

戻り値

増加する値のシーケンスの iota_view

解説

無制限シーケンスの場合、データ型の最大値に達した後の動作は未定義です。

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

ストリームの要素に対してビューを作成します。

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

パラメーター

str
ストリーム オブジェクト。 その型は、 std::basic_istreamの特殊化から派生します。

Val
ストリームから抽出する要素の型。

戻り値

basic_istream_view

この範囲アダプターは、 ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str)と同じです。ここで、 Ustrの種類です。

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

複数の範囲のすべての要素を 1 つのビューに結合するビューを作成します。

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

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

パラメーター

R
基になる範囲の型。

rg
ビューを作成する範囲。

戻り値

基になる範囲内のすべての範囲の要素を格納する join_view

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

解説

前に "2)" として示したコードは、パイプ構文 ( collection | join) と共に使用できます。 または、関数呼び出し構文 ( join(collection)) と共に使用することもできます。

keys

コレクション内の各タプルに似た値に最初のインデックスの keys_view を作成します。 これは、連想コンテナーからキーを抽出する場合に便利です。 たとえば、 std::tuple<string, int>の範囲を指定すると、各タプルのすべての string 要素で構成されるビューを作成します。

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

パラメーター

R
基になる範囲の型。

戻り値

範囲内の各タプルに似た値への最初のインデックスで構成される keys_view

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

区切り記号に基づいて範囲をサブ範囲に分割します。 区切り記号には、1 つの要素または要素のビューを指定できます。

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

パラメーター

delimiter
1 つの値、または範囲を分割する場所を指定する値のシーケンス。

Pattern
区切り記号の型。

R
分割する範囲の型。

rg
分割する範囲。

戻り値

1 つ以上のサブ範囲を含み、delimiterの元の範囲を分割した結果であるlazy_split_view

解説

区切り記号は結果の一部ではありません。 たとえば、値2の範囲1,2,3を分割すると、13の 2 つのサブ範囲が表示されます。

関連するアダプターが split。 [split_view](split-view-class.md) and lazy_split_view' の主な違いは次のとおりです。

表示 const範囲を分割できます 範囲反復子
split_view いいえ forward_range以上をサポート
lazy_split_view はい input_range 以上

const範囲を分割する必要がない限り、split_viewの方が効率的です。

前に "2)" として示したコードは、パイプ構文 ( collection | lazy_split(delimiter)) と共に使用できます。 または、関数呼び出し構文 ( lazy_split(collection, delimiter) または lazy_split(delimiter)(collection)) と共に使用することもできます。

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

範囲の要素のビューを逆の順序で作成します。

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

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

パラメーター

R
反転する基になる範囲の型。

rg
反転する範囲。

戻り値

基になる範囲の要素を逆の順序で表示するビュー。 返されるビューは通常、 reverse_viewの特殊化であるとは限りません。 つまり、

  • Vreverse_viewの特殊化である場合、結果は引数の基になるビューになります。 ダブルリバースは、操作なし (操作なし) です。
  • Vフォームがsubrange<reverse_iterator<I>, reverse_iterator<I>>場合、結果はラップされていない反復子のsubrangeになります。 ダブルリバースはノーオペレーションです。
  • それ以外の場合、結果は reverse_view です。

解説

前に "2)" として示したコードは、パイプ構文 ( collection | reverse) と共に使用できます。 または、関数呼び出し構文 ( reverse(collection)) と共に使用することもできます。

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

1 つの要素を含むビューである single_viewを作成します。

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

パラメーター

T
ビュー内の要素の型。

t
ビューに格納する要素の値。

戻り値

tを含むsingle_view

解説

このビューは、少なくとも 1 つの要素を含むビューで提供する必要があるコードを呼び出すために、テスト目的で役立ちます。

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

区切り記号に基づいてビューをサブ範囲に分割します。 区切り記号には、1 つの要素または要素のシーケンスを指定できます。

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

パラメーター

delimiter
1 つの値、または範囲を分割する場所を指定する値のシーケンス。

Pattern
区切り記号の型。

R
分割する基になる範囲の型。

rg
分割する範囲。

戻り値

1 つ以上のサブ範囲を含む split_view

解説

区切り記号は結果の一部ではありません。 たとえば、値2の範囲1,2,3を分割すると、13の 2 つのサブ範囲が表示されます。

関連するアダプターが lazy_splitsplit_viewlazy_split_viewの主な違いは次のとおりです。

表示 const範囲を分割できます 範囲の種類
split_view いいえ forward_range以上をサポート
lazy_split_view はい input_range以上をサポート

const範囲を分割する必要がない限り、split_viewの方が効率的です。

前に "2)" として示したコードは、パイプ構文 ( collection | split(delimiter)) と共に使用できます。 または、関数呼び出し構文 ( split(collection, 5) または split(5)(collection)) と共に使用することもできます。

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

範囲の先頭から取得した指定した数の要素を含むビューを作成します。

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

パラメーター

R
基になる範囲の型。

rg
ビューを作成する範囲。

count
rgの前面から取得する要素の数。

戻り値

返されるビューは通常、 take_viewの特殊化であるとは限りません。 具体的には、次のように使用します。

解説

rgに存在する要素よりも多くの要素を指定すると、すべての要素が取得されます。

takedropの反対です。

前に "2)" として示したコードは、パイプ構文 ( collection | take(5)) と共に使用できます。 または、関数呼び出し構文 ( take(5, collection) または take(5)(collection)) と共に使用することもできます。

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

指定した条件に一致する範囲の先頭要素を含むビューを作成します。

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

パラメーター

P
述語の型。

predicate
範囲からコピーする先頭の要素を決定する条件。

R
基になる範囲の型。

rg
ビューを作成する範囲。

戻り値

範囲内の指定した条件を満たす最初のcount要素で構成されるtake_while_view

解説

述語がfalseを返した後、または範囲が要素を使い切った後、rgから要素の取得を停止します。

take_whiledrop_whileの反対です。

前に "2)" として示したコードは、パイプ構文 ( collection | take_while(pred)) と共に使用できます。 または、関数呼び出し構文 ( take_while(collection, pred) または take_while(pred)(collection)) と共に使用することもできます。

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

要素のビューを作成します。それぞれのビューは、指定された範囲内の要素の変換です。

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

パラメーター

F
要素を変換する関数オブジェクトの型。

R
基になる範囲の型。

fun
要素を変換する関数。

rg
ビューを作成する範囲。

戻り値

rgの変換された要素を含むtransform_view

解説

効率を高めるために、 filtertransformを作成するときは、最初に filter を実行して、保持する要素のみを transform します。

前に "2)" として示したコードは、パイプ構文 ( collection | transform(fun)) と共に使用できます。 または、関数呼び出し構文 ( transform(collection, fun) または transform(fun)(collection)) と共に使用することもできます。

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

コレクション内の各タプルに似た値に 2 番目のインデックスで構成される values_view を作成します。 これは、連想コンテナー内の値を表示する場合に便利です。 たとえば、 std::tuple<string, int> 値の範囲を指定すると、各タプルのすべての int 要素で構成されるビューが作成されます。

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

パラメーター

R
基になる範囲の型。

rg
タプルに似た値の基になる範囲。

戻り値

2 番目のインデックスから範囲内の各タプルに似た値に構築された values_view

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

範囲アダプターの種類のエイリアス

all_t

allが返すビューの型を提供します。

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

パラメーター

R
基になる範囲の型。

戻り値

all返されるビューの型: decltype(views::all(std::declval<R>()))

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

関連項目

<ranges>
<ranges> 概念
クラスの表示