Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the output_iterator Concept not require the output_iterator_tag?

C++20 introduces proper Concepts for the different types of iterators in the standard library (input, output, forward, bidirectional, random access, ...).

While the original named requirements for those types did not mention the iterator tags from std::iterator_traits at all, the new C++20 concepts explicitly require them. See for example the input_iterator Concept ([iterator.concept.input]):

template<class I>
  concept input_iterator =
    input_or_output_iterator<I> &&
    indirectly_readable<I> &&
    requires { typename ITER_CONCEPT(I); } &&
    derived_from<ITER_CONCEPT(I), input_iterator_tag>;

Notice the check for the iterator tag in the last line. All the iterator concepts check for the respective tag like this, except output iterator. Output iterator has always been special in this regard, since the early days of the Ranges TS:

Unlike the output iterator requirements in the C++ standard, OutputIterator in the Ranges TS does not require that the iterator category tag be defined.

What is the reason for this special treatment for output iterators?

like image 974
ComicSansMS Avatar asked Jul 11 '20 11:07

ComicSansMS


1 Answers

In C++20, iterator categories are in general detected automatically based on syntax. Explicitly use of the iterator tags are only used for opt-out or opt-in:

  • everything weaker than random_access_iterator_tag is used to opt out of a stronger iterator category (for example, an input iterator might be syntactically indistinguishable from a forward iterator);
  • contiguous_iterator_tag is used to opt into contiguous_iterator, since contiguity is a relative rare property that also can't be syntactically detected.

Output iterators have no need for this kind of fine-grained control - either you can or you can't write to it, and that's detected syntactically.


As to when opt-in/opt-out are provided, Casey Carter explained:

  • Passing an argument to a library component that constrains that argument is an implicit claim that the argument either doesn't satisfy the constraint (doesn't meet the syntactic requirements) or that it does model the constraint (meets the syntax and the semantic requirements) so opt-in/opt-out are not generally necessary.

  • opt-in/opt-out facilities are only provided when we want to enable the library to assume that an argument that models some concept X additionally models some refinement Y of X when it satisfies Y. (I've been calling this "semantic promotion", but it's not a well-established term.) The choice of opt-in vs. opt-out depends on the expected frequency of false positives.

"Semantic promotion" is often done on non-output iterator arguments. Output iterators have nothing to be promoted to.

like image 186
T.C. Avatar answered Oct 12 '22 21:10

T.C.