Implement LWG-4125 move_iterator's default constructor should be constrained - #6322
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements the LWG-4125 resolution, which constrains move_iterator's default constructor so it only participates when the underlying iterator type is default-initializable. This also resolves the long-standing Clang/EDG divergence described in #3377 (LLVM-60293) by ensuring the default constructor is genuinely absent — rather than present-but-deleted via a default member initializer — for non-default-initializable iterators.
Changes:
- In
<xutility>,move_iterator's defaulted default constructor gains arequires default_initializable<_Iter>constraint (C++20), and the_Currentmember initializer changes from list-init{}to value-init_Iter()(C++17) to avoid wrongly selecting aninitializer_listconstructor; in C++14 the default constructor becomes user-provided (: _Current()) and intentionally non-constexpr. - Adds tests for the new constraint, including a new
empty_list_input_iterhelper that is initializable via{}but not value-initializable. - Removes the now-unnecessary
__clang__/__EDG__workaround in thejoin_withtest that previously guarded the range-of-rvalue delimiter case.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
stl/inc/xutility |
Constrains move_iterator() with default_initializable<_Iter> (C++20), switches the member initializer to value-init, and restructures the constructor across C++14/17/20 modes. |
tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp |
Adds empty_list_input_iter and static_asserts validating default_initializable<move_iterator<...>> and iterator-category metaprogramming. |
tests/std/tests/P2441R2_views_join_with/test.cpp |
Removes the LLVM-60293/VSO-1900294 workaround now that the root cause is fixed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
96916e3 to
a66163b
Compare
|
I'm mirroring this to the MSVC-internal repo. Please notify me if any further changes are pushed, otherwise no action is required. |
3731b3d
into
microsoft:main
🚚 😻 🎁 |
Fixes #6314. Fixes #3377 (by making LLVM-60293 and VSO-1900294 no longer relevant).
Unblocked libcxx test(s):
std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cppRemarks:
= _Iter();in C++14 mode. Due to lack of guaranteed copy elision in C++14, such default member initializer would cause one more move construction when RVO is not performed. The move construction is required to be well-formed, and in most (but not all) situations it won't cause side effects.{}accepts invalid cases. E.g.empty_list_input_iteradded to the test file can be direct-list-initialized from{}, but can't be value initialized. So the default constructor ofempty_list_input_itershould be ill-formed in old modes.