namespace std {
template<input_or_output_iterator I, sentinel_for<I> S>
requires (!same_as<I, S> && copyable<I>)
class common_iterator {
private:
variant<I, S> v_; // 説明専用メンバ変数
};
// incrementable_traitsにアダプトする
template<class I, class S>
struct incrementable_traits<common_iterator<I, S>> {
using difference_type = iter_difference_t<I>;
};
// iterator_traitsにアダプトする
template<input_iterator I, class S>
struct iterator_traits<common_iterator<I, S>> {
using iterator_concept = /*see below*/;
using iterator_category = /*see below*/; // 定義されない場合がある
using value_type = iter_value_t<I>;
using difference_type = iter_difference_t<I>;
using pointer = /*see below*/;
using reference = iter_reference_t<I>;
};
}
概要
common_iterator
は、イテレータ型と番兵型が異なる範囲についてそれぞれをラップして、同じ範囲を表しながらイテレータ型と番兵型を共通化させるためのイテレータ/番兵アダプタである。
同じ範囲についてのイテレータ/番兵を保持して、等値比較演算子を適切に実装することで共通化を行う。
メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++20 |
operator= |
代入演算子 | C++20 |
operator* |
間接参照演算子 | C++20 |
operator-> |
メンバアクセス演算子 | C++20 |
operator++ |
イテレータをインクリメントする | C++20 |
非メンバ(Hidden friends)関数
名前 | 説明 | 対応バージョン |
---|---|---|
operator== |
等値比較 | C++20 |
operator!= |
非等値比較 (== により使用可能) |
C++20 |
operator- |
2つのcommon_iterator の差を求める |
C++20 |
iter_move |
イテレータの要素の移動 | C++20 |
iter_swap |
イテレータの要素の交換 | C++20 |
iterator_traits
の型
名前 | 説明 | 対応バージョン |
---|---|---|
iterator_concept |
forward_iterator_tag ただし、 I がforward_iterator のモデルではない場合はinput_iterator_tag |
C++20 |
iterator_category |
forward_iterator_tag ただし、 iterator_traits<I>::iterator_category がderived_from<forward_iterator_tag> のモデルではない場合はinput_iterator_tag |
C++20 |
value_type |
iter_value_t<I> |
C++20 |
difference_type |
iter_difference_t<I> |
C++20 |
pointer |
void ただし、 operator-> が利用可能である場合はその戻り値型 |
C++20 |
reference |
iter_reference_t<I> |
C++20 |
iterator_category
はiter_difference_t<I>
が組み込みの整数型の場合にのみ定義される(integer-class型の場合には定義されない)
例
#include <iostream>
#include <iterator>
#include <ranges>
// イテレータによって範囲の要素を出力する
// イテレータ型と番兵型が同一であることを前提とするレガシーな実装
template<typename I>
void iter_output(I it, I end) {
for (;it != end; ++it) {
std::cout << *it << std::endl;
}
}
int main() {
auto seq = std::views::iota(1) | std::views::take(5);
// 範囲seqはイテレータ型と番兵型が異なっているためそのままだとエラー
//iter_output(std::ranges::begin(seq), std::ranges::end(seq));
// common_iteratorを通すことでイテレータ型と番兵型を合わせる
using CI = std::common_iterator<std::ranges::iterator_t<decltype(seq)>, std::ranges::sentinel_t<decltype(seq)>>;
auto it = CI{std::ranges::begin(seq)};
auto end = CI{std::ranges::end(seq)};
iter_output(it, end);
}
出力
1
2
3
4
5
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 9 ✅