名前空間
変種
操作

std::random_access_iterator

From cppreference.com
 
 
イテレータライブラリ
イテレータのコンセプト
random_access_iterator
(C++20)


イテレータのプリミティブ
アルゴリズムのコンセプトとユーティリティ
間接呼び出し可能コンセプト
共通アルゴリズム要件
(C++20)
(C++20)
(C++20)
ユーティリティ
(C++20)
イテレータアダプタ
Rangeアクセス
(C++11)(C++14)
(C++14)(C++14)  
(C++11)(C++14)
(C++14)(C++14)  
(C++17)(C++20)
(C++17)
(C++17)
 
ヘッダ <iterator> で定義
template< class I >

    concept random_access_iterator =
        std::bidirectional_iterator<I> &&
        std::derived_from</*ITER_CONCEPT*/<I>, std::random_access_iterator_tag> &&
        std::totally_ordered<I> &&
        std::sized_sentinel_for<I, I> &&
        requires(I i, const I j, const std::iter_difference_t<I> n) {
            { i += n } -> std::same_as<I&>;
            { j +  n } -> std::same_as<I>;
            { n +  j } -> std::same_as<I>;
            { i -= n } -> std::same_as<I&>;
            { j -  n } -> std::same_as<I>;
            {  j[n]  } -> std::same_as<std::iter_reference_t<I>>;

        };
(C++20以降)

Concept random_access_iterator は、+=, +, -=, - 演算子による定数時間での前進、- 演算子による定数時間での距離計算、添字演算子 [] による配列表記のサポートを追加することで、bidirectional_iterator を改良します。

目次

[編集] イテレータコンセプトの決定

このコンセプトの定義は、展示専用のエイリアステンプレート /*ITER_CONCEPT*/ を介して指定されます。

Determine /*ITER_CONCEPT*/<I> するために、ITER_TRAITS<I> を、特殊化 std::iterator_traits<I> がプライマリテンプレートから生成されている場合は I 、それ以外の場合は std::iterator_traits<I> とします。

  • ITER_TRAITS<I>::iterator_concept が有効で型名を指定する場合、/*ITER_CONCEPT*/<I> はその型を表します。
  • そうでなければ、ITER_TRAITS<I>::iterator_category が有効で型名を指定する場合、/*ITER_CONCEPT*/<I> はその型を表します。
  • そうでなければ、std::iterator_traits<I> がプライマリテンプレートから生成される場合、/*ITER_CONCEPT*/<I>std::random_access_iterator_tag を表します。
  • そうでなければ、/*ITER_CONCEPT*/<I> は型を表さず、置換失敗となります。

[edit] 意味論的要件

a および b を型 I の有効なイテレータとし、ba から到達可能であり、nstd::iter_difference_t<I> 型の値で b - a に等しいとします。std::random_access_iterator<I> は、それが包含するすべてのコンセプトがモデル化されており、かつ、

  • (a += n)b に等しい場合にのみモデル化されます。
  • std::addressof(a += n)std::addressof(a) に等しいです。[1]
  • (a + n)(a += n) に等しいです。
  • (a + n)(n + a) に等しいです。
  • 任意の2つの正の整数 xy について、a + (x + y) が有効であれば、a + (x + y)(a + x) + y に等しいです。
  • a + 0a に等しいです。
  • もし (a + (n - 1)) が有効であれば、--b(a + (n - 1)) に等しいです。
  • (b += -n)(b -= n) は両方とも a に等しいです。
  • std::addressof(b -= n)std::addressof(b) に等しいです。[1]
  • (b - n)(b -= n) に等しいです。
  • もし b が間接参照可能であれば、a[n] は有効であり、*b に等しいです。
  • bool(a <= b)true です。
  • すべての必須操作は定数時間複雑性を持っています。

std::addressof はイテレータオブジェクトのアドレスを返し、イテレータが指すオブジェクトのアドレスを返さないことに注意してください。つまり、operator+= および operator-=*this への参照を返す必要があります。

[編集] 等価性保持

標準ライブラリのコンセプトのrequiresで宣言された式は、(特に明記されていない限り)等価性保持である必要があります。

[編集] 暗黙の式バリエーション

一部の定数左辺値オペランドに対して非変更的である式を使用するrequiresは、暗黙の式バリエーションも必要とする。

[edit] 注記

LegacyRandomAccessIterator」要件とは異なり、random_access_iterator コンセプトは、間接参照が左辺値を返すことを要求しません。

[edit]

C++20 コンセプトを介した std::distance の可能な実装を示します。

#include <iterator>
 
namespace cxx20
{
    template<std::input_or_output_iterator Iter>
    constexpr std::iter_difference_t<Iter> distance(Iter first, Iter last)
    {
        if constexpr(std::random_access_iterator<Iter>)
            return last - first;
        else
        {
            std::iter_difference_t<Iter> result{};
            for (; first != last; ++first)
                ++result;
            return result;
        }
    }
}
 
int main()
{
    static constexpr auto il = {3, 1, 4};
 
    static_assert(std::random_access_iterator<decltype(il.begin())> &&
                  cxx20::distance(il.begin(), il.end()) == 3 &&
                  cxx20::distance(il.end(), il.begin()) == -3);
}

[edit] 関連項目

forward_iterator が、後方への移動をサポートする双方向イテレータであることを規定する
(コンセプト) [編集]
メモリ上で連続する要素を参照する、random_access_iterator が連続イテレータであることを指定します。
(コンセプト) [編集]
English 日本語 中文(简体) 中文(繁體)