- iterator[meta header]
- std[meta namespace]
- concept[meta id-type]
- cpp20[meta cpp]
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>>>;
};
}- derived_from[link /reference/concepts/derived_from.md]
- ITER_CONCEPT[link /reference/iterator/input_iterator.md#iter_concept]
- contiguous_iterator_tag[link /reference/iterator/iterator_tag.md]
- is_lvalue_reference_v[link /reference/type_traits/is_lvalue_reference.md]
- iter_reference_t[link /reference/iterator/iter_reference_t.md]
- to_address[link /reference/memory/to_address.md]
- add_pointer_t[link /reference/type_traits/add_pointer.md]
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>");
}- std::contiguous_iterator[color ff0000]
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 [mark verified]
- Visual C++: 2019 Update 6 [mark verified]