yohhoyの日記

技術的メモをしていきたい日記

イテレータに->演算子オーバーロードは必要?

C++標準ライブラリが定める InputIterator 要件(requirement) と input_iteratorコンセプト(concept) の変遷についてメモ。

まとめ:

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 expression i->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 type T, called the value type of the iterator. (snip)

1 Types that are readable by applying operator* model the readable concept, including pointers, smart pointers, and iterators.

template<class In>
  concept readable =
    /*(snip)*/;

2 Given a value i of type I, I models readable 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 models input_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 for readable (23.3.4.2)) and which can be both pre- and post-incremented. [Note: Unlike the Cpp17InputIterator requirements (23.3.5.2), the input_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-> が追加された。

C++03

Input iterator要件はoperator->オーバーロードを要求する。 C++03 24.1.1 Table 72より該当箇所を引用。

operation
a->m
semantics, pre/post-condition
pre: (*a).m is well-defined
Equivalent to (*a).m

C++03時点では、istreambuf_iterator::operator->は提供されない。


関連URL