diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 77666c2ba4a..95900a911bc 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5412,7 +5412,8 @@ void random_shuffle(_RanIt _First, _RanIt _Last) { // shuffle [_First, _Last) us #if _HAS_CXX20 _EXPORT_STD template -constexpr _FwdIt shift_left(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift) { +constexpr _FwdIt shift_left( + _FwdIt _First, const _FwdIt _Last, typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) { // shift [_First, _Last) left by _Pos_to_shift // positions; returns the end of the resulting range _STL_ASSERT(_Pos_to_shift >= 0, "shift count must be non-negative (N4950 [alg.shift]/1)"); @@ -5446,7 +5447,8 @@ constexpr _FwdIt shift_left(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_Fwd } _EXPORT_STD template = 0> -_FwdIt shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift) noexcept /* terminates */ { +_FwdIt shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, + typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) noexcept /* terminates */ { // shift [_First, _Last) left by _Pos_to_shift positions // not parallelized as benchmarks show it isn't worth it _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt); @@ -5454,7 +5456,8 @@ _FwdIt shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Po } _EXPORT_STD template -constexpr _FwdIt shift_right(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift) { +constexpr _FwdIt shift_right( + _FwdIt _First, const _FwdIt _Last, typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) { // shift [_First, _Last) right by _Pos_to_shift // positions; returns the beginning of the resulting range _STL_ASSERT(_Pos_to_shift >= 0, "shift count must be non-negative (N4950 [alg.shift]/5)"); @@ -5528,7 +5531,8 @@ constexpr _FwdIt shift_right(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_Fw } _EXPORT_STD template = 0> -_FwdIt shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift) noexcept /* terminates */ { +_FwdIt shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, + typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) noexcept /* terminates */ { // shift [_First, _Last) right by _Pos_to_shift positions // not parallelized as benchmarks show it isn't worth it _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt); diff --git a/stl/inc/xutility b/stl/inc/xutility index e97140ac360..48d77a3b4b7 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1464,7 +1464,8 @@ constexpr _InIt _Next_iter(_InIt _First) { // increment iterator } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 _InIt next(_InIt _First, _Iter_diff_t<_InIt> _Off = 1) { // increment iterator +_NODISCARD _CONSTEXPR17 _InIt next( + _InIt _First, typename iterator_traits<_InIt>::difference_type _Off = 1) { // increment iterator static_assert(_Is_ranges_input_iter_v<_InIt>, "next requires input iterator"); _STD advance(_First, _Off); @@ -1477,7 +1478,8 @@ constexpr _BidIt _Prev_iter(_BidIt _First) { // decrement iterator } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 _BidIt prev(_BidIt _First, _Iter_diff_t<_BidIt> _Off = 1) { // decrement iterator +_NODISCARD _CONSTEXPR17 _BidIt prev( + _BidIt _First, typename iterator_traits<_BidIt>::difference_type _Off = 1) { // decrement iterator static_assert(_Is_ranges_bidi_iter_v<_BidIt>, "prev requires bidirectional iterator"); _STD advance(_First, -_Off); diff --git a/tests/std/test.lst b/tests/std/test.lst index 825f2055c25..ee4fa316ece 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -732,3 +732,4 @@ tests\VSO_0849827_multicontainer_emplace_hint_position tests\VSO_0938757_attribute_order tests\VSO_0961751_hash_range_erase tests\VSO_0971246_legacy_await_headers +tests\VSO_1925201_iter_traits diff --git a/tests/std/tests/VSO_1925201_iter_traits/env.lst b/tests/std/tests/VSO_1925201_iter_traits/env.lst new file mode 100644 index 00000000000..d6d824b5879 --- /dev/null +++ b/tests/std/tests/VSO_1925201_iter_traits/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_20_matrix.lst diff --git a/tests/std/tests/VSO_1925201_iter_traits/test.compile.pass.cpp b/tests/std/tests/VSO_1925201_iter_traits/test.compile.pass.cpp new file mode 100644 index 00000000000..35d0eeff053 --- /dev/null +++ b/tests/std/tests/VSO_1925201_iter_traits/test.compile.pass.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +// Defend against regression of DevCom-10532126, in which several function templates used +// `_Iter_diff_t` as a parameter type instead of the specified +// `typename iterator_traits::difference_type`. The two are equivalent in C++17, but in C++20 +// _Iter_diff_t becomes iter_difference_t. We thought the difference was not observable, +// but it interferes with concept overloading. + +using std::iter_value_t, std::iterator_traits, std::same_as; +using std::next, std::prev, std::shift_left, std::shift_right; + +struct meow {}; + +constexpr meow* nil = nullptr; + +template +concept Meowerator = same_as, meow>; + +template +void next(I, typename iterator_traits::difference_type = 1) {} + +template +void prev(I, typename iterator_traits::difference_type = 1) {} + +template +void shift_left(I, I, typename iterator_traits::difference_type) {} +template +void shift_right(I, I, typename iterator_traits::difference_type) {} +// Note that we intentionally do not test the ExecutionPolicy overloads of shift_meow. They are +// constrained via an unspecified mechanism to "not participate in overload resolution unless +// is_execution_policy_v is true", effectively making concept overloading +// impossible (or at least non-portable). + +static_assert(same_as); +static_assert(same_as); + +static_assert(same_as); +static_assert(same_as); + +#ifndef __clang__ // TRANSITION, LLVM-75404 +static_assert(same_as); +static_assert(same_as); +#endif // TRANSITION, LLVM-75404