Open frederick-vs-ja opened 9 months ago
IMO a "fix" could be implementing `_Iter_value_t` like the following since C++20.
```C++
template
Perhaps we can add an internal typedef name to this specialization for workaround: https://github.com/microsoft/STL/blob/8b081e26ba016970ce3338cb483ff10f2ade30a5/stl/inc/__msvc_iter_core.hpp#L153-L155
We talked about this at the weekly maintainer meeting, although @CaseyCarter was out sick so our analysis powers were limited. This was introduced by #329. Switching ugly _Iter_value_t
to be C++20 iter_value_t
with different semantics appears to be a bug for the reasons you've explained, but #329 said that this was to "enable unwrapping of C++20 move-only single-pass iterators". It appears that many uses of ugly _Iter_value_t
can't possibly be handling such C++20 move-only single-pass iterators (because the uses are in stable_sort()
etc. where stronger iterators are required).
We believe that a full audit of all ugly _Iter_value_t
usage will be necessary, to determine which ones:
iterator_traits::value_type
iterator_traits::value_type
and C++20 iter_value_t
iter_value_t
In general, we should avoid having aliases that switch their semantics based on Standard mode, except when explicitly commented/known that their downlevel behavior is a "best effort" approximation with no harmful downsides (e.g. <xutility>
's _Iterator_is_contiguous
is ok).
We believe that a full audit of all ugly
_Iter_value_t
usage will be necessary, to determine which ones:
- Should always expand to
iterator_traits::value_type
- Should have this behavior of conditionally switching between
iterator_traits::value_type
and C++20iter_value_t
- Should always be C++20
iter_value_t
Per WG21-P2248R7, it seems that the value type should be consistently iterator_traits::value_type
for non-ranges algorithms. Perhaps conditionally switching is only applicable to move_iterator
and reverse_iterator
's value_type
.
Filed LWG-4080 for this.
Describe the bug
Currently, MSVC STL defines
_Iter_value_t
in term ofiter_value_t
since C++20 and uses it in non-ranges algorithms.https://github.com/microsoft/STL/blob/8b081e26ba016970ce3338cb483ff10f2ade30a5/stl/inc/xutility#L1167-L1168 https://github.com/microsoft/STL/blob/8b081e26ba016970ce3338cb483ff10f2ade30a5/stl/inc/xutility#L1177-L1178
Per [readable.traits], if a type
I
has mismatched member typesvalue_type
andelement_type
, theniter_value_t<I>
is ill-formed by default (when there's no program-definedindirectly_readable_traits
oriterator_traits
specializations), and thusI
doesn't satisfy any C++20 `meow_
iteratorconcept. However,
Ican still meet _Cpp17MeowIterator_ requirements because the legacy requirements don't consider
element_type`, so such strategy sometimes rejects valid programs.For example, this example should be valid since C++17. But MSVC STL starts to reject it since C++20 while other implementations don't (Godbolt link).
Expected behavior
This example compiles in C++20/23 modes as in C++17.
STL version
Probably every version from 1e8b8d4eef4b2dddeb7533c5231c876383bd0ea6 to 8b081e26ba016970ce3338cb483ff10f2ade30a5.
Additional context
WG21-P2408R5 complicated the situation.
meow
iterator
concepts, which would newly require well-formedness ofiter_value_t
in some cases. Butstd::sort
wasn't affected.meow
iterator
and Cpp17MeowIterator.