最終更新日時: 2025年07月10日 10時26分30秒 (JST)
Koichi Murase が更新

履歴 編集

concept
<iterator>

# std::contiguous_iterator(C++20)

    namespace std {
      template<class I>
      concept contiguous_iterator =
        random_access_iterator<I> &&
        derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> &&
        is_lvalue_reference_v<iter_reference_t<I>> &&
        same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> &&
        requires(const I& i) {
          { to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>;
        };
    }

## 概要

`contiguous_iterator`は、イテレータ型`I`が隣接イテレータであることを表すコンセプトである。

`contiguous_iterator`となるイテレータは、ランダムアクセスイテレータであり、参照する要素列がメモリ上で連続していることが保証される。

C++20で導入された`contiguous_iterator`は、要素がメモリー上で連続していることを保証しているが、C++23の標準ライブラリ実装では 得られたポインタに対してさらなるポインタ演算を行う演算は許可されていなかった。

しかし、C++26からは、この制限が緩和され、`std::to_address`関数を使用して得られたポインタに対してさらなるポインタ演算を行うことができるようになった。

## モデル

`a, b`を間接参照可能なイテレータ、`c`を間接参照不可能なイテレータとし、`b`は`a`から、`c`は`b`からそれぞれ到達可能であるとする。そのような型`I`のイテレータ`a, b, c`と`iter_difference_t<I>`の示す型`D`について次の条件を満たす場合に限って、型`I`は`contiguous_iterator`のモデルである。

## 要件

- C++26: このイテレータの範囲`[i, s)`はポインタ範囲`[to_address(i), to_address(i + ranges::distance(i, s)))`に置き換えて使用することが実装に許可される
  - 注：このイテレータをアルゴリズム適用した場合、イテレータのインクリメントが一回しか起こらない可能性があり、個々のインクリメントに対して副作用を起こすことを期待してはならない
  - 備考：連続イテレータの範囲に対する操作として、`std::copy()`の実装が`std::memmove()`の呼び出しで完了するなど、イテレータを一つずつ進めるのではなくメモリ操作で高速実装されることを許可するものである

## 例

    #include <iostream>
    #include <concepts>
    #include <iterator>
    #include <vector>
    #include <forward_list>
    #include <list>
    #include <deque>

    template<std::contiguous_iterator I>
    void f(const char* name) {
      std::cout << name << " is contiguous_iterator" << std::endl;
    }

    template<typename I>
    void f(const char* name) {
      std::cout << name << " is not contiguous_iterator" << std::endl;
    }

    int main() {
      f<int*>("int*");
      f<const int*>("const int*");
      f<std::vector<int>::iterator>("std::vector<int>::iterator");

      std::cout << "\n";
      f<int* const>("int* const");
      f<std::forward_list<int>::iterator>("std::forward_list<int>::iterator");
      f<std::list<int>::iterator>("std::list<int>::iterator");
      f<std::deque<int>::iterator>("std::deque<int>::iterator");
      f<std::istream_iterator<double>>("std::istream_iterator<double>");
      f<std::ostream_iterator<double>>("std::ostream_iterator<double>");
    }

### 出力

    int* is contiguous_iterator
    const int* is contiguous_iterator
    std::vector<int>::iterator is contiguous_iterator

    int* const is not contiguous_iterator
    std::forward_list<int>::iterator is not contiguous_iterator
    std::list<int>::iterator is not contiguous_iterator
    std::deque<int>::iterator is not contiguous_iterator
    std::istream_iterator<double> is not contiguous_iterator
    std::ostream_iterator<double> is not contiguous_iterator

## バージョン

### 言語

- C++20

### 処理系

- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 6 ✅

## 関連項目

- C++20 コンセプト

## 参照

- P0896R4 The One Ranges Proposal (was Merging the Ranges TS)
- P1474R1 Helpful pointers for `ContiguousIterator`
- P3349R1 Converting contiguous iterators to pointers