<ranges> エイリアスのテンプレート

エイリアス テンプレートは別の型のエイリアスであり、コードをより読みやすくすることができます。 たとえば、次のエイリアスconditional_tは、渡されるrangeの種類に応じて、borrowed_rangeまたはdangling範囲のエイリアスです。

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <span>
#include <algorithm>
#include <ranges>
#include <type_traits>

using namespace std;

// Define an alias template called my_iterator_t
// If the provided range R is a borrowed_range, then the 
// returned type is iterator_t<R>; otherwise, ranges::dangling
template<ranges::range R>
using my_iterator_t = conditional_t<
    ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

int main()
{
    my_iterator_t<list<int>> aDanglingRange; // list<> isn't a borrowed_range
    constexpr bool same = same_as<
        decltype(aDanglingRange),
        ranges::dangling>; // true

    my_iterator_t<span<int, 5>> anIterator_t; // span<> is a borrowed_range
    constexpr bool same2 = same_as<
        decltype(anIterator_t),
        ranges::iterator_t<span<int, 5>>>; // true

    cout << boolalpha << same << "," << same2; // outputs true, true
}

エイリアス テンプレートの詳細については、「 Aliases と typedefsを参照してください。

<algorithm> ヘッダーは、rangeの反復子とセンチネルの種類を決定する次のエイリアス テンプレートを定義します。

エイリアス テンプレート 説明
borrowed_iterator_tC++20 rangeに対して返される反復子が、有効期間が終了した範囲を参照しているかどうかを判断します。
borrowed_subrange_tC++20 rangeに対して返されるsubrangeが、有効期間が終了した範囲を参照しているかどうかを判断します。
danglingC++20 range/subrangeの返された反復子が、それが参照するrange/subrangeの有効期間を上回っていることを示します。
iterator_tC++20 指定した範囲の反復子の型を返します。
range_difference_tC++20 指定した範囲の反復子の差分型を返します。
range_reference_tC++20 指定した範囲の反復子の参照型を返します。
range_rvalue_reference_tC++20 指定した範囲の反復子の右辺値参照型を返します。 つまり、範囲の要素の右辺値参照型です。
range_size_tC++20 指定した範囲の sizeを報告するために使用する型を返します。
range_value_tC++20 指定した範囲の反復子の値型を返します。 または、範囲内の要素の型です。
sentinel_tC++20 指定した範囲のセンチネルの種類を返します。

borrowed_iterator_t

反復子を返すアルゴリズム関数が右辺値 range 引数を使用して呼び出されると、範囲の有効期間は呼び出しの後で終了する可能性があります。 つまり、返される反復子は、有効期間が終了した要素を参照できます。 未解決の反復子を使用すると、未定義の動作が発生します。

このテンプレート エイリアスは、指定された範囲引数の状況であることを示す ranges::dangling を返します。または、返された反復子を使用しても安全であることを示す std::ranges::iterator_t<R> 。これは、モデルを参照する範囲 borrowed_range 、または範囲が左辺値として渡されたためです。

template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

パラメーター

R
テストする範囲。

解説

右辺値範囲の有効期間は、範囲モデルが borrowed_range かどうかに関係なく、関数呼び出しの後で終了できます。 borrowed_rangeの場合、範囲の有効期間がいつ終了しても、適切に定義された動作で反復子を引き続き使用できる場合があります。

たとえば、コンテナーの有効期間が終了すると、反復子は破棄された要素を参照するため、 vectorlist などのコンテナーでは、これが当てはまらない場合です。

たとえば、borrowed_rangeの反復子を引き続き使用できます。たとえば、反復子がオンデマンドで生成されるために破棄されない値のセットを超えるiota_view<int>{0, 42}などのviewに対して使用できます。

アルゴリズム関数が反復子の有効期間に依存する範囲を渡すと、反復子またはサブ範囲の代わりに ranges::dangling が返されるため、コンパイル時に誤用の可能性が検出されます。

例: borrowed_iterator_t

次の例は、 borrowed_iterator_t が未解決の反復子を検出する方法を示しています。 関数 ranges::max_element() は、このテンプレート エイリアスを使用して戻り値の型を決定します。

// requires /std:c++20, or later

#include <vector>
#include <span>
#include <ranges>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    // Not dangling ------------------

    int a[] = {0,1,2,3};

    // not dangling even though an rvalue because span models ranges::borrowed
    auto result1 = ranges::max_element(span{a});
    cout << boolalpha << ranges::borrowed_range<decltype(span{a})> << endl; // outputs true because the temporary models ranges::borrowed
    cout << same_as<decltype(result1), ranges::dangling> << endl; // outputs false because the result isn't dangling

    vector<int> v{0,1,2,3}; // doesn't model ranges::borrowed
    auto result2 = ranges::max_element(v); // Yet not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling> << endl; // outputs false because the result isn't dangling
    
    // Dangling ------------------

    auto result3 = ranges::max_element(vector{0,1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << same_as<decltype(result3), ranges::dangling>; // outputs true because the result is dangling
}
true
false
false
true

borrowed_subrange_t

右辺値range引数を指定してsubrangeを返すアルゴリズム関数が呼び出されると、呼び出しの後で範囲の有効期間が終了する可能性があります。 つまり、返された subrange は、有効期間が終了した要素を参照できます。 未解決の subrange を使用すると、未定義の動作が発生します。

このテンプレートエイリアスは、指定された範囲引数の状況である可能性があることを示す ranges::dangling を返すか、返されたサブ範囲を使用しても安全であることを示 subrange<ranges::iterator_t<R>> 。これは、モデルを参照する要素が borrowed_range または範囲が左辺値として渡された範囲であるためです。

template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
    ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;

パラメーター

R
テストする範囲。

解説

右辺値範囲の有効期間は、範囲モデルが borrowed_range かどうかに関係なく、関数呼び出しの後で終了できます。 borrowed_rangeの場合、範囲の有効期間がいつ終了しても、適切に定義された動作で反復子を引き続き使用できる場合があります。

たとえば、コンテナーの有効期間が終了すると、反復子は破棄された要素を参照するため、 vectorlist などのコンテナーでは、これが当てはまらない場合です。

たとえば、borrowed_rangeの反復子を引き続き使用できます。たとえば、反復子がオンデマンドで生成されるために破棄されない値のセットを超えるiota_view<int>{0, 42}などのviewに対して使用できます。

反復子が有効期間に依存する範囲にアルゴリズム関数が渡された場合、コンパイル時に誤用の可能性が検出されるように、サブ範囲の代わりに ranges::dangling が返されます。

例: borrowed_subrange_t

次の例は、equal_range()max_elementがこのテンプレート エイリアスを使用して戻り値の型を判断するため、borrowed_subrange_tが未解決の反復子を検出する方法を示しています。

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <algorithm>
#include <span>
#include <ranges>

int main()
{
    using namespace std;

    // Not dangling ------------------

    vector vec{0, 1, 1, 2};

    auto result1 = ranges::equal_range(span{vec}, 1); // not dangling even though passing as an rvalue because span models borrowed_range
    cout << boolalpha << ranges::borrowed_range<decltype(span{vec})> << endl;  // true because the temporary is a borrowed range
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // false because the result isn't dangling

    // result2 isn't dangling even though vec doesn't model ranges::borrowed because it's an lvalue
    auto result2 = ranges::max_element(vec);
    cout << boolalpha << ranges::borrowed_range<decltype(vec)> << endl;  // false because vector isn't a borrowed_range
    cout << boolalpha << same_as<decltype(result2), ranges::dangling> << endl; // false because the result isn't dangling

    // Dangling -----------------------

    // result3 is dangling because the temporary is an rvalue that doesn't model borrowed_range
    auto result3 = ranges::max_element(vector{0,1,1,2});
    cout << boolalpha << same_as<decltype(result3), ranges::dangling> << endl; // true because the result is dangling
}
true
false
false
false
true

dangling

反復子または subrange を返すアルゴリズム関数が右辺値 range 引数を使用して呼び出された場合、範囲引数の有効期間は呼び出しの後で終了する可能性があります。 つまり、返された反復子または subrange は、有効期間が終了した要素を参照できます。 未解決の反復子または subrange を使用すると、未定義の動作が発生します。

アルゴリズム関数が反復子の有効期間に依存する範囲を渡すと、コンパイル時に誤用の可能性が検出されるように、反復子またはサブ範囲の代わりに ranges::dangling が返されます。

1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}

パラメーター

Args
void以外の型の可変数。 効果はありません。 引数は便利なので、反復子型と dangling 型の構築を処理するために異なるコード パスが必要ありません。 これは、渡された値が反復子の代わりに dangling を返す必要があることを示す場合に便利です。

例: dangling

次の例は、 max_element が未解決の反復子を検出する方法を示しています。

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>
#include <algorithm>

using namespace std;

int main()
{
    auto result1 = ranges::max_element(vector{1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // outputs true because the result is dangling

    vector<int> v{3,4,5};
    auto result2 = ranges::max_element(v); // Not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling>; // outputs false because the result isn't dangling
}
true
false

iterator_t

このテンプレート エイリアスは、指定された範囲の型を反復処理するために使用される反復子型を返します。

template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));

パラメーター

T
反復子の型を取得する範囲の型。

例: iterator_t

次の例は、 iterator_t を使用してベクターの反復子を宣言する方法を示しています。

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::iterator_t<decltype(v)> it = v.begin();
    cout << *it << "\n"; // outputs 1
    cout << typeid(it).name(); // outputs class _Vector_iterator<class _Vector_val<struct _Simple_types<int>>>
}
1
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >

range_difference_t

指定した範囲の反復子の差分型を返します。

template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;

パラメーター

R
反復子が差分型を提供する範囲。

例: range_difference_t

次の例は、 range_difference_t を使用して範囲内の要素間の距離を保持する方法を示しています。

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    auto findIt = ranges::find(v, 2);
    // type of distance is ptrdiff_t
    ranges::range_difference_t<decltype(v)> distance = ranges::distance(v.begin(), findIt);
    cout << distance << endl; // outputs 1
}
1

range_reference_t

指定した範囲の反復子の参照型を返します。 つまり、範囲の要素の参照型です。

template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;

パラメーター

R
反復子型の参照型が返される範囲。

例: range_reference_t

次の例は、範囲内の要素の型を参照する range_reference_t を示しています。

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_reference_t<decltype(v)> ref = v[0];

    cout << ref << endl; // outputs 1
    cout << typeid(ref).name() << endl; // outputs int
}
1
int

range_rvalue_reference_t

指定した範囲の反復子の右辺値参照型を返します。 つまり、範囲の要素の右辺値参照型です。

template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;

パラメーター

R
右辺値参照型を反復子型に取得する範囲。

例: range_rvalue_reference_t

次の例は、範囲内の要素の右辺値型を参照する range_rvalue_reference_t を示しています。

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_rvalue_reference_t<decltype(v)> elementRvalueType = v[0] * 10; // elementRvalueType is int&& 

    cout << elementRvalueType << endl; // outputs 10
    cout << typeid(elementRvalueType).name() << endl; // outputs int
}
10
int

range_size_t

指定したsized_rangesize関数の型を返します。

template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;

パラメーター

R
size関数の型を取得する範囲。

例: range_size_t

次の例は、範囲内の要素の数を参照する range_size_t を示しています。

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_size_t<decltype(v)> size = v.size();
    cout << size << endl; // outputs 3
    cout << typeid(size).name(); // outputs unsigned __int64
}
3
unsigned __int64

range_value_t

指定した範囲の反復子の値型を返します。 または、範囲内の要素の型です。

template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;

パラメーター

R
反復子の値型を取得する範囲。

例: range_value_t

次の例は、 range_value_t が範囲内の要素の型を参照する方法を示しています。

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};
    ranges::range_value_t<decltype(v)> elementType = v[2]; // elementType is an int 

    cout << elementType << endl; // outputs 3
    cout << typeid(elementType).name() << endl; // outputs int
}
3
unsigned int

sentinel_t

指定した範囲のセンチネルの種類を返します。

template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));

パラメーター

R
Sentinel の種類を取得する範囲。

例: sentinel_t

次の例は、 sentinel_t を使用して、反復子の型とセンチネルの型が同じかどうかを判断する方法を示しています。

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <ranges>

int main()
{
    using namespace std;

    list myList{1, 2, 3};
    ranges::subrange count = std::views::counted(myList.begin(), myList.size());

    ranges::iterator_t<decltype(count)> first;
    ranges::sentinel_t<decltype(count)> last;

    // The iterator type and the sentinel type of a subrange
    // obtained from views::counted are not the same
    cout << boolalpha << is_same<decltype(first), decltype(last)>::value << endl; // outputs false
    cout << "iter: " << typeid(first).name() << "\n\n end: " << typeid(last).name() << endl;
}
false
iter: class std::counted_iterator<class std::_List_iterator<class std::_List_val<struct std::_List_simple_types<int> > > >

 end: struct std::default_sentinel_t

関連項目

<ranges>
範囲アダプター
クラスの表示