- iterator[meta header]
- std[meta namespace]
- concept[meta id-type]
- cpp20[meta cpp]
namespace std {
template<class I>
concept weakly_incrementable =
movable<I> &&
requires(I i) {
typename iter_difference_t<I>;
requires is-signed-integer-like<iter_difference_t<I>>;
{ ++i } -> same_as<I&>; // 等しさを保持することを要求しない
i++; // 等しさを保持することを要求しない
};
}
- movable[link /reference/concepts/movable.md]
- iter_difference_t[link /reference/iterator/iter_difference_t.md]
- is-signed-integer-like[link /reference/iterator/is_integer_like.md]
weakly_incrementable
は、イテレータ型I
が前置/後置インクリメント演算子(operator++
)によってインクリメント可能であることを表すコンセプトである。
そのようなインクリメント操作には等しさを保持することは要求されず、型I
は等値比較可能(equality_comparable
)である必要もない。
型I
のオブジェクトi
について次の条件を満たす場合に限って、型I
はweakly_incrementable
のモデルである。
++i
とi++
は同じ定義域を持つi
がインクリメント可能ならば、++i
とi++
はi
を次の要素へ進めるi
がインクリメント可能ならば、addressof(++i)
とaddressof(i)
は等値となる
「i
がインクリメント可能」というのは、i
が前置/後置両方のインクリメント式(++
)の定義域にある場合を言う。すなわち、一般的なイテレータ範囲のend
などインクリメントが出来ない、あるいは未定義動作を引き起こすような状態にi
が無い場合を指定している。
このコンセプトはイテレータにマルチパス保証を要求しない。例えばイテレータa, b
がある時、a == b
であっても++a == ++b
となるとは限らない。すなわち、weakly_incrementable
なイテレータはその操作によってイテレータが参照しているシーケンスの状態が変更されることを許可する。そのようなイテレータには例えばistream_iterator
がある。
#include <iostream>
#include <concepts>
#include <iterator>
#include <memory>
#include <vector>
template<std::weakly_incrementable I>
void f(const char* name) {
std::cout << name << " is weakly incrementable" << std::endl;
}
template<typename I>
void f(const char* name) {
std::cout << name << " is not weakly incrementable" << std::endl;
}
struct sample_weak_incrementable {
friend auto operator++(sample_weak_incrementable&) -> sample_weak_incrementable&;
friend auto operator++(sample_weak_incrementable&, int) -> sample_weak_incrementable&;
// これも必要
using difference_type = int;
};
struct sample_not_weak_incrementable {
// 前置++しか用意しない
friend auto operator++(sample_weak_incrementable&) -> sample_weak_incrementable&;
using difference_type = int;
};
int main() {
f<int*>("int*");
f<const int*>("const int*");
f<std::vector<int>::iterator>("std::vector<int>::iterator");
f<std::ostream_iterator<double>>("std::ostream_iterator<double>");
f<sample_weak_incrementable>("sample_weak_incrementable");
std::cout << "\n";
f<int* const>("int* const");
f<std::unique_ptr<int>>("std::unique_ptr<int>");
f<sample_not_weak_incrementable>("sample_not_weak_incrementable");
}
- std::weakly_incrementable[color ff0000]
int* is weakly incrementable
const int* is weakly incrementable
std::vector<int>::iterator is weakly incrementable
std::ostream_iterator<double> is weakly incrementable
sample_incrementable is weakly incrementable
int* const is not weakly incrementable
std::unique_ptr<int> is not weakly incrementable
sample_not_incrementable is not weakly incrementable
- C++20
- Clang: ??
- GCC: 10.1 [mark verified]
- Visual C++: 2019 Update 6 [mark verified]