Range TS idioms and the mysterious auto &&

后端 未结 1 1485
粉色の甜心
粉色の甜心 2020-12-20 15:12

In pre-Range TS code, I might do something like the following to get a (potentially modifiable) reference to a ForwardIterator\'s value:

auto &val = *it;         


        
相关标签:
1条回答
  • 2020-12-20 15:34

    This idiom is being used because the Range TS and the C++20-equivalent actually requires this idiom. The reason for this requirement has to do with the fact that proxy iterators are now legal constructs for all categories of iterators.

    A proxy iterator's operator* does not return a value_type&; it returns a prvalue of an object that acts like an reference. Therefore, if you tried to store a reference to the value with auto&, your code would fail to compile with a proxy iterator.

    The Range TS's iterator concepts never require that the return value from operator* is actually a language reference. The Readable concept only requires that the return value is convertible to a value_type. The Writable concept only requires that a value_type can be assigned to the return value.

    So code getting references from iterators of all kinds under the Range feature must now use auto&&, which can bind to prvalues without making them const. So when dealing with ranges, if you want to get a possibly non-const reference to the value, auto&& is the most convenient way. If you want just a const reference, you can continue to use const auto &.


    Note that auto&& also handles iterators that directly return prvalues of type value_type from their operator*. Obviously these are only useful for Readable iterators, but they're quite useful. The simplest example would be an iterator for a counting range over some number of integers. The iterator returns an int, not a reference to some memory. Such iterators can be RandomAccessIterators in the Range TS due to not having a hard requirement for returning a language reference.

    Such iterators would also make sense for regular expression matching. The current regex_iterator returns a reference to an internal object; that's necessary for being a ForwardIterator. Instead, it could have been much smaller by having operator* do the search and return the match object as a prvalue. But the old system wouldn't allow that.

    Given such an iterator, auto& cannot be used to capture "references" to their results.

    0 讨论(0)
提交回复
热议问题