Search code examples
c++iteratorc++20c++-concepts

What is the difference between std::input_or_output_iterator and std::indirectly_readable?


Reading about these concepts, in common words I see both of these concepts should allow to "dereference" an instance of the type. I can see they also have some other requirements, but they seem secondary. So why the need for 2 concepts, semantically speaking?

EDIT: My current understanding of them is as if std::indirectly_readable + std::indirectly_writable => close to std::input_or_output_iterator


Solution

  • input_or_output_iterator and indirectly_readable are two halves of input_iterator.

    indirectly_writable and input_or_output_iterator are almost the two halves of output_iterator (there is also *it++ = blah).

    input_or_output_iterator requires ++ to be somewhat sensible (both semantically and syntactically), and requires that whatever type *it is, taking a reference of it is legal (ie, it isn't void, as void& is not a legal type).

    indirectly_readable and indirectly_writable place extra requirements on *it so you can (plausibly) read/write it.

    indirectly_writable requires *it = blah to work.

    indirectly_readable demands std::iter_value_t, std::iter_reference_t, std::iter_rvalue_reference_t all exist and that they have "sensible" relationships to each other and to *it.

    The reference types of std::input_iterator need not be actual references. But if they aren't actual references, you have to be careful about how const& and && play with them, as these clauses are really modelled to work for references:

    std::common_reference_with<
      std::iter_reference_t<In>&&, std::iter_value_t<In>&
    > &&
    std::common_reference_with<
      std::iter_reference_t<In>&&, std::iter_rvalue_reference_t<In>&&
    > &&
    std::common_reference_with<
      std::iter_rvalue_reference_t<In>&&, const std::iter_value_t<In>&
    >;
    

    on references, those clauses basically require that your reference type be related to your value type, your rvalue reference type be related to your reference type, and your rvalue reference type be related to a const& reference to your value type.

    Returning a value from *it does work (like int).

    Doing this with "magic" reference types is going to be challenging. I do not believe specializing https://en.cppreference.com/w/cpp/types/common_reference is legal.