C++標準ライブラリが定める InputIterator 要件(requirement) と input_iterator
コンセプト(concept) の変遷についてメモ。
まとめ:
- C++2a(C++20)
input_iterator
コンセプトではイテレータ型にoperator*
オーバーロードのみ要求する。operator->
オーバーロードは要求されない。 - C++17以前の InputIterator 要件では、イテレータ型に対して
operator*
とoperator->
オーバーロードの両方を要求する。
N4835(C++2a WD)
Cpp17InputIterator要件はoperator->
オーバーロードを要求するが、input_iterator
コンセプトはoperator->
オーバーロードを要求しない。
C++2aに向けて採択された提案文書(PDF)P0896R4では、[iterator.requirements.general]セクションから下記Wordingが明示的に削除されている。
An iterator
i
for which the expression(*i).m
is well-defined supports the expressioni->m
with the same semantics as(*i).m
.
N4835*1 23.2, 23.3.1/p1, 23.3.4.2/p1-2, 23.3.4.6/p1, 23.3.4.9/p1, 23.3.5.2 Table 83より一部引用。
Header <iterator> synopsis
namespace std { template<class T> using with-reference = T&; // exposition only template<class T> concept can-reference // exposition only = requires { typename with-reference<T>; }; template<class T> concept dereferenceable // exposition only = requires(T& t) { { *t } -> can-reference; // not required to be equality-preserving }; // (snip) }
1 Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges) in a uniform manner. To be able to construct template algorithms that work correctly and efficiently on different types of data structures, the library formalizes not just the interfaces but also the semantics and complexity assumptions of iterators. An input iterator
i
supports the expression*i
, resulting in a value of some object typeT
, called the value type of the iterator. (snip)
1 Types that are readable by applying
operator*
model thereadable
concept, including pointers, smart pointers, and iterators.template<class In> concept readable = /*(snip)*/;2 Given a value
i
of typeI
,I
modelsreadable
only if the expression*i
is equality-preserving. [Note: The expression*i
is indirectly required to be valid via the exposition-only dereferenceable concept (23.2). -- end note]
1 The
input_or_output_iterator
concept forms the basis of the iterator concept taxonomy; every iterator modelsinput_or_output_iterator
. This concept specifies operations for dereferencing and incrementing an iterator. Most algorithms will require additional operations to compare iterators with sentinels (23.3.4.7), to read (23.3.4.9) or write (23.3.4.10) values, or to provide a richer set of iterator movements (23.3.4.11, 23.3.4.12, 23.3.4.13).template<class I> concept input_or_output_iterator = requires(I i) { { *i } -> can-reference; } && weakly_incrementable<I>;
1 The
input_iterator
concept defines requirements for a type whose referenced values can be read (from the requirement forreadable
(23.3.4.2)) and which can be both pre- and post-incremented. [Note: Unlike the Cpp17InputIterator requirements (23.3.5.2), theinput_iterator
concept does not need equality comparison since iterators are typically compared to sentinels. -- end note]template<class I> concept input_iterator = input_or_output_iterator<I> && readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;
Table 83: Cpp17InputIterator requirements (in addition to Cpp17Iterator)
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- Expects:
a
is dereferenceable.
C++17
Input iterator要件はoperator->
オーバーロードを要求する。 C++17 27.2.3 Table 95より該当箇所を引用。
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- Requires:
a
is dereferenceable.
C++17以降、LWG DR 2790にて istreambuf_iterator::operator->
は削除された。
C++11/14
Input iterator要件はoperator->
オーバーロードを要求する。 C++11 24.2.3 Table 107より該当箇所を引用。C++14でも同一。
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- pre:
a
is dereferenceable.
C++11以降、LWG DR 659にて istreambuf_iterator::operator->
が追加された。