- Continue exposing contiguous_iterator_tag only in C++20.
- Implement C++20's changes to reverse_iterator, so that it won't be accidentally counted as a contiguous iterator (and test this).
- Implement C++20's changes to move_iterator as well (and test them).
- move_iterator should not be contiguous. This fixes a bug where we optimized std::copy-of-move-iterators in an observable way. Add a regression test for that bugfix.
- Add libcxx tests for __is_cpp17_contiguous_iterator of all relevant standard iterator types (in all modes).
- Expose {reverse,move}_iterator::iterator_concept only in C++20 mode. I initially exposed it in all modes, but now that contiguous_iterator_tag is C++20-only, I think this makes more sense.
I expect this to solve the issue reported by @rnk in D92776. They should just be able to write a conforming contiguous iterator according to https://stackoverflow.com/questions/65712091/in-c20-how-do-i-write-a-contiguous-iterator
libc++ will guarantee that it works (i.e. is optimized in std::copy) in C++20 mode, but will continue not to support user-defined contiguous iterators in C++17.
I would perhaps like to rename __unwrap_iter(x) to something like __unwrap_contiguous_iter(x) or __lower_contiguous_iter(x), to better reflect its purpose; but I didn't want to do that in this patch because it would just add icky diffs at all the call-sites.
Can you name this __apply? Or we could use operator(). Either seems closer to conventions than __f.