diff --git a/stl/inc/iterator b/stl/inc/iterator index 180abaa4c2..48089f6d0a 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1467,27 +1467,39 @@ struct iterator_traits> : iterator_traits<_Iter> { _STD_END _STDEXT_BEGIN -using _STD iterator_traits; using _STD size_t; template -class checked_array_iterator { // wrap a pointer with checking - static_assert(_STD is_pointer_v<_Ptr>, "checked_array_iterator requires pointers"); +class _DEPRECATE_STDEXT_ARR_ITERS checked_array_iterator { // wrap a pointer with checking +private: + using _Pointee_type = _STD remove_pointer_t<_Ptr>; + static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>, + "checked_array_iterator requires pointers to objects"); public: - using iterator_category = typename iterator_traits<_Ptr>::iterator_category; - using value_type = typename iterator_traits<_Ptr>::value_type; - using difference_type = typename iterator_traits<_Ptr>::difference_type; - using pointer = typename iterator_traits<_Ptr>::pointer; - using reference = typename iterator_traits<_Ptr>::reference; + using iterator_category = _STD random_access_iterator_tag; + using value_type = _STD remove_cv_t<_Pointee_type>; + using difference_type = _STD ptrdiff_t; + using pointer = _Ptr; + using reference = _Pointee_type&; +#ifdef __cpp_lib_concepts + using iterator_concept = _STD contiguous_iterator_tag; +#endif // __cpp_lib_concepts - constexpr checked_array_iterator() noexcept : _Myarray(nullptr), _Mysize(0), _Myindex(0) {} + constexpr checked_array_iterator() = default; constexpr checked_array_iterator(const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept : _Myarray(_Array), _Mysize(_Size), _Myindex(_Index) { _STL_VERIFY(_Index <= _Size, "checked_array_iterator construction index out of range"); } + _STL_DISABLE_DEPRECATED_WARNING + template , int> = 0> + constexpr operator checked_array_iterator() const noexcept { + return checked_array_iterator{_Myarray, _Mysize, _Myindex}; + } + _STL_RESTORE_DEPRECATED_WARNING + _NODISCARD constexpr _Ptr base() const noexcept { return _Myarray + _Myindex; } @@ -1658,32 +1670,47 @@ public: } private: - _Ptr _Myarray; // beginning of array - size_t _Mysize; // size of array - size_t _Myindex; // offset into array + _Ptr _Myarray = nullptr; // beginning of array + size_t _Mysize = 0; // size of array + size_t _Myindex = 0; // offset into array }; +_STL_DISABLE_DEPRECATED_WARNING template -_NODISCARD constexpr checked_array_iterator<_Ptr> make_checked_array_iterator( - const _Ptr _Array, const size_t _Size, const size_t _Index = 0) { +_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD constexpr checked_array_iterator<_Ptr> make_checked_array_iterator( + const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept { return checked_array_iterator<_Ptr>(_Array, _Size, _Index); } +_STL_RESTORE_DEPRECATED_WARNING template -class unchecked_array_iterator { // wrap a pointer without checking, to silence warnings - static_assert(_STD is_pointer_v<_Ptr>, "unchecked_array_iterator requires pointers"); +class _DEPRECATE_STDEXT_ARR_ITERS unchecked_array_iterator { // wrap a pointer without checking, to silence warnings +private: + using _Pointee_type = _STD remove_pointer_t<_Ptr>; + static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>, + "unchecked_array_iterator requires pointers to objects"); public: - using iterator_category = typename iterator_traits<_Ptr>::iterator_category; - using value_type = typename iterator_traits<_Ptr>::value_type; - using difference_type = typename iterator_traits<_Ptr>::difference_type; - using pointer = typename iterator_traits<_Ptr>::pointer; - using reference = typename iterator_traits<_Ptr>::reference; + using iterator_category = _STD random_access_iterator_tag; + using value_type = _STD remove_cv_t<_Pointee_type>; + using difference_type = _STD ptrdiff_t; + using pointer = _Ptr; + using reference = _Pointee_type&; +#ifdef __cpp_lib_concepts + using iterator_concept = _STD contiguous_iterator_tag; +#endif // __cpp_lib_concepts - constexpr unchecked_array_iterator() noexcept : _Myptr(nullptr) {} + constexpr unchecked_array_iterator() = default; constexpr explicit unchecked_array_iterator(const _Ptr _Src) noexcept : _Myptr(_Src) {} + _STL_DISABLE_DEPRECATED_WARNING + template , int> = 0> + constexpr operator unchecked_array_iterator() const noexcept { + return unchecked_array_iterator{_Myptr}; + } + _STL_RESTORE_DEPRECATED_WARNING + _NODISCARD constexpr _Ptr base() const noexcept { return _Myptr; } @@ -1802,15 +1829,35 @@ public: } private: - _Ptr _Myptr; // underlying pointer + _Ptr _Myptr = nullptr; // underlying pointer }; +_STL_DISABLE_DEPRECATED_WARNING template -_NODISCARD unchecked_array_iterator<_Ptr> make_unchecked_array_iterator(const _Ptr _It) noexcept { +_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD unchecked_array_iterator<_Ptr> make_unchecked_array_iterator( + const _Ptr _It) noexcept { return unchecked_array_iterator<_Ptr>(_It); } +_STL_RESTORE_DEPRECATED_WARNING _STDEXT_END +#if _HAS_CXX20 +_STD_BEGIN +_STL_DISABLE_DEPRECATED_WARNING +template +struct pointer_traits<_STDEXT checked_array_iterator<_Ty*>> { + using pointer = _STDEXT checked_array_iterator<_Ty*>; + using element_type = _Ty; + using difference_type = ptrdiff_t; + + _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { + return _Iter._Unwrapped(); + } +}; +_STL_RESTORE_DEPRECATED_WARNING +_STD_END +#endif // _HAS_CXX20 + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ceb2fce5ed..ea78d77138 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1445,7 +1445,19 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define _CXX23_DEPRECATE_DENORM #endif // ^^^ warning disabled ^^^ -// next warning number: STL4043 +#if _HAS_CXX17 && !defined(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _DEPRECATE_STDEXT_ARR_ITERS \ + [[deprecated( \ + "warning STL4043: stdext::checked_array_iterator, stdext::unchecked_array_iterator, and related factory " \ + "functions are non-Standard extensions and will be removed in the future. std::span (since C++20) " \ + "and gsl::span can be used instead. You can define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING or " \ + "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to suppress this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_ARR_ITERS +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4044 // next error number: STL1006 diff --git a/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp b/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp index 93b4ead540..5718201bf0 100644 --- a/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp +++ b/tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS #include diff --git a/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp b/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp index 5addf960bd..a1f8f5b611 100644 --- a/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp +++ b/tests/std/tests/Dev10_709166_checked_and_unchecked_array_iterator/test.cpp @@ -1,15 +1,74 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include +#include #include +#include +#include #include #include #include +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template +void check_checked_array_iterator_category_and_convertibility() { + STATIC_ASSERT(std::is_same_v::iterator_category, + std::random_access_iterator_tag>); + + STATIC_ASSERT(std::is_same_v::value_type, std::remove_cv_t>); + + STATIC_ASSERT(std::is_same_v::difference_type, std::ptrdiff_t>); + + STATIC_ASSERT(std::is_same_v::pointer, T*>); + + STATIC_ASSERT(std::is_same_v::reference, T&>); + + STATIC_ASSERT(std::is_convertible_v, stdext::checked_array_iterator>); + +#ifdef __cpp_lib_concepts + STATIC_ASSERT( + std::is_same_v::iterator_concept, std::contiguous_iterator_tag>); + + STATIC_ASSERT(std::contiguous_iterator>); +#endif // __cpp_lib_concepts +} + +template +void check_unchecked_array_iterator_category_and_convertibility() { + STATIC_ASSERT(std::is_same_v::iterator_category, + std::random_access_iterator_tag>); + + STATIC_ASSERT(std::is_same_v::value_type, std::remove_cv_t>); + + STATIC_ASSERT(std::is_same_v::difference_type, std::ptrdiff_t>); + + STATIC_ASSERT(std::is_same_v::pointer, T*>); + + STATIC_ASSERT(std::is_same_v::reference, T&>); + + STATIC_ASSERT( + std::is_convertible_v, stdext::unchecked_array_iterator>); + +#ifdef __cpp_lib_concepts + STATIC_ASSERT( + std::is_same_v::iterator_concept, std::contiguous_iterator_tag>); + + STATIC_ASSERT(std::contiguous_iterator>); +#endif // __cpp_lib_concepts +} + int main() { { + check_checked_array_iterator_category_and_convertibility(); + check_checked_array_iterator_category_and_convertibility(); + check_checked_array_iterator_category_and_convertibility>(); + + int* const p = new int[9]; for (int i = 0; i < 9; ++i) { @@ -19,31 +78,28 @@ int main() { auto cat = stdext::make_checked_array_iterator(p, 9); - static_assert(std::is_same_v>, - "stdext::make_checked_array_iterator(p, 9)'s return type is wrong!"); - - - auto dog = stdext::make_checked_array_iterator(p, 9, 3); - - static_assert(std::is_same_v>, - "stdext::make_checked_array_iterator(p, 9, 3)'s return type is wrong!"); - + STATIC_ASSERT(std::is_same_v>); - static_assert( - std::is_same_v::iterator_category, std::random_access_iterator_tag>, - "stdext::checked_array_iterator::iterator_category is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(cat) == &*cat); + assert(std::to_address(cat + 8) == &*cat + 8); + assert(std::to_address(cat + 8) == std::to_address(cat) + 8); + assert(std::to_address(cat + 9) == std::to_address(cat) + 9); +#endif // _HAS_CXX20 - static_assert(std::is_same_v::value_type, int>, - "stdext::checked_array_iterator::value_type is wrong!"); - static_assert(std::is_same_v::difference_type, ptrdiff_t>, - "stdext::checked_array_iterator::difference_type is wrong!"); + auto dog = stdext::make_checked_array_iterator(p, 9, 3); - static_assert(std::is_same_v::pointer, int*>, - "stdext::checked_array_iterator::pointer is wrong!"); + STATIC_ASSERT(std::is_same_v>); - static_assert(std::is_same_v::reference, int&>, - "stdext::checked_array_iterator::reference is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(dog) == &*dog); + assert(std::to_address(dog + 5) == &*dog + 5); + assert(std::to_address(dog + 5) == std::to_address(dog) + 5); + assert(std::to_address(dog - 3) == &*dog - 3); + assert(std::to_address(dog - 3) == std::to_address(dog) - 3); + assert(std::to_address(dog + 6) == std::to_address(dog) + 6); +#endif // _HAS_CXX20 { @@ -184,6 +240,11 @@ int main() { } { + check_unchecked_array_iterator_category_and_convertibility(); + check_unchecked_array_iterator_category_and_convertibility(); + check_unchecked_array_iterator_category_and_convertibility>(); + + int* const p = new int[9]; for (int i = 0; i < 9; ++i) { @@ -193,31 +254,28 @@ int main() { auto cat = stdext::make_unchecked_array_iterator(p); - static_assert(std::is_same_v>, - "stdext::make_unchecked_array_iterator(p)'s return type is wrong!"); + STATIC_ASSERT(std::is_same_v>); +#if _HAS_CXX20 + assert(std::to_address(cat) == &*cat); + assert(std::to_address(cat + 8) == &*cat + 8); + assert(std::to_address(cat + 8) == std::to_address(cat) + 8); + assert(std::to_address(cat + 9) == std::to_address(cat) + 9); +#endif // _HAS_CXX20 - auto dog = stdext::make_unchecked_array_iterator(p + 3); - - static_assert(std::is_same_v>, - "stdext::make_unchecked_array_iterator(p + 3)'s return type is wrong!"); + auto dog = stdext::make_unchecked_array_iterator(p + 3); - static_assert( - std::is_same_v::iterator_category, std::random_access_iterator_tag>, - "stdext::unchecked_array_iterator::iterator_category is wrong!"); - - static_assert(std::is_same_v::value_type, int>, - "stdext::unchecked_array_iterator::value_type is wrong!"); - - static_assert(std::is_same_v::difference_type, ptrdiff_t>, - "stdext::unchecked_array_iterator::difference_type is wrong!"); - - static_assert(std::is_same_v::pointer, int*>, - "stdext::unchecked_array_iterator::pointer is wrong!"); + STATIC_ASSERT(std::is_same_v>); - static_assert(std::is_same_v::reference, int&>, - "stdext::unchecked_array_iterator::reference is wrong!"); +#if _HAS_CXX20 + assert(std::to_address(dog) == &*dog); + assert(std::to_address(dog + 5) == &*dog + 5); + assert(std::to_address(dog + 5) == std::to_address(dog) + 5); + assert(std::to_address(dog - 3) == &*dog - 3); + assert(std::to_address(dog - 3) == std::to_address(dog) - 3); + assert(std::to_address(dog + 6) == std::to_address(dog) + 6); +#endif // _HAS_CXX20 { diff --git a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp index 4e7f0833bc..754b6a632f 100644 --- a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp +++ b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp index f9ea851fcc..64e3e9d2cf 100644 --- a/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp +++ b/tests/std/tests/Dev11_0000000_null_forward_iterators/test.cpp @@ -3,6 +3,7 @@ #define _SILENCE_CXX23_ALIGNED_UNION_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #include #include diff --git a/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp b/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp index 771425af7e..dce64b8444 100644 --- a/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp +++ b/tests/std/tests/P0040R3_extending_memory_management_tools/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index aee2e256ee..45b77573ce 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include #include diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp index 7ade4b41b1..690dd4be34 100644 --- a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp @@ -18,6 +18,7 @@ #define _SILENCE_CXX20_REL_OPS_DEPRECATION_WARNING #define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING #define _USE_NAMED_IDL_NAMESPACE 1 diff --git a/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp b/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp index 91aee8682f..f5da03d273 100644 --- a/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp +++ b/tests/std/tests/VSO_0299624_checked_array_iterator_idl/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING + #include #include