From ba8b40de7fa0243a6f3ac3605347828d8e60e584 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Mon, 13 Nov 2023 17:12:34 +0100 Subject: [PATCH 1/2] Implement P2836R1 --- stl/inc/xutility | 13 +++ stl/inc/yvals_core.h | 3 +- .../P2278R4_basic_const_iterator/test.cpp | 86 ++++++++++++++++++- .../test.compile.pass.cpp | 2 +- 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 5755411c1b..8b2f7efeb9 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2155,6 +2155,19 @@ public: return _Current == _Se; } + template <_Not_a_const_iterator _Other> + requires _Constant_iterator<_Other> && convertible_to + _NODISCARD constexpr operator _Other() const& noexcept( + is_nothrow_convertible_v) /* strengthened */ { + return _Current; + } + + template <_Not_a_const_iterator _Other> + requires _Constant_iterator<_Other> && convertible_to<_Iter, _Other> + _NODISCARD constexpr operator _Other() && noexcept(is_nothrow_convertible_v<_Iter, _Other>) /* strengthened */ { + return _STD move(_Current); + } + _NODISCARD constexpr bool operator<(const basic_const_iterator& _Right) const noexcept(noexcept(_Fake_copy_init(_Current < _Right._Current))) // strengthened requires random_access_iterator<_Iter> diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 1c494ad110..350b1e22fa 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -383,6 +383,7 @@ // P2693R1 Formatting thread::id And stacktrace // P2713R1 Escaping Improvements In std::format // P2763R1 Fixing layout_stride's Default Constructor For Fully Static Extents +// P2836R1 basic_const_iterator Should Follow Its Underlying Type's Convertibility // _HAS_CXX23 and _SILENCE_ALL_CXX23_DEPRECATION_WARNINGS control: // P1413R3 Deprecate aligned_storage And aligned_union @@ -1831,7 +1832,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_out_ptr 202106L #define __cpp_lib_print 202207L -#define __cpp_lib_ranges_as_const 202207L +#define __cpp_lib_ranges_as_const 202311L #define __cpp_lib_ranges_as_rvalue 202207L #define __cpp_lib_ranges_cartesian_product 202207L #define __cpp_lib_ranges_chunk 202202L diff --git a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp index a21fbf8635..ea69c8fa26 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp +++ b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp @@ -298,7 +298,89 @@ constexpr void instantiation_test() { instantiator::call>(); } -int main() { - static_assert((instantiation_test(), true)); +template +struct tracking_input_iterator { +public: + using value_type = remove_const_t; + using difference_type = ptrdiff_t; + + constexpr tracking_input_iterator() = default; + + constexpr tracking_input_iterator(const tracking_input_iterator&) : copied{true} {} + + constexpr tracking_input_iterator(tracking_input_iterator&&) : moved{true} {} + + template + requires convertible_to + constexpr tracking_input_iterator(const tracking_input_iterator&) : copied{true} {} + + template + requires convertible_to + constexpr tracking_input_iterator(tracking_input_iterator&&) : moved{true} {} + + tracking_input_iterator& operator=(const tracking_input_iterator&) = default; + tracking_input_iterator& operator=(tracking_input_iterator&&) = default; + + constexpr tracking_input_iterator& operator++(); // not defined + constexpr void operator++(int); // not defined + T& operator*() const; // not defined + + constexpr bool is_moved() const { + return moved; + } + + constexpr bool is_copied() const { + return copied; + } + +private: + bool copied = false; + bool moved = false; +}; + +static_assert(input_iterator>); +static_assert(!_Constant_iterator>); +static_assert(_Constant_iterator>); + +// P2836R1 basic_const_iterator Should Follow Its Underlying Type's Convertibility +constexpr void test_p2836r1() { + { // Code from P2836R1 + std::vector v; + auto t = v | views::take_while([](int const x) { return x < 100; }); + auto f = [](std::vector::const_iterator) {}; + auto i2 = std::ranges::cbegin(t); + f(i2); // Error before P2836R1 + } + + { + tracking_input_iterator i; + basic_const_iterator ci{i}; + + tracking_input_iterator j1 = ci; + assert(j1.is_copied()); + assert(!j1.is_moved()); + + tracking_input_iterator j2 = move(ci); + assert(!j2.is_copied()); + assert(j2.is_moved()); + + // Incorrect conversions + static_assert(!constructible_from, const decltype(ci)&>); + static_assert(!constructible_from, decltype(ci)>); + + // Non-const target iterator + static_assert(!constructible_from, const decltype(ci)&>); + static_assert(!constructible_from, decltype(ci)>); + } +} + +constexpr bool all_tests() { instantiation_test(); + test_p2836r1(); + return true; +} + +int main() { + static_assert(all_tests()); + all_tests(); } diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 3ab7a981fe..0d37160705 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -674,7 +674,7 @@ STATIC_ASSERT(__cpp_lib_ranges == 202110L); #endif #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 -STATIC_ASSERT(__cpp_lib_ranges_as_const == 202207L); +STATIC_ASSERT(__cpp_lib_ranges_as_const == 202311L); #elif defined(__cpp_lib_ranges_as_const) #error __cpp_lib_ranges_as_const is defined #endif From 61eb3a90bd07eb07705b4c20bd57c1d570645825 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Nov 2023 14:54:22 -0800 Subject: [PATCH 2/2] Style nitpicks. --- .../P2278R4_basic_const_iterator/test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp index ea69c8fa26..6db5eca75b 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp +++ b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp @@ -299,7 +299,7 @@ constexpr void instantiation_test() { } template -struct tracking_input_iterator { +class tracking_input_iterator { public: using value_type = remove_const_t; using difference_type = ptrdiff_t; @@ -325,14 +325,14 @@ struct tracking_input_iterator { constexpr void operator++(int); // not defined T& operator*() const; // not defined - constexpr bool is_moved() const { - return moved; - } - constexpr bool is_copied() const { return copied; } + constexpr bool is_moved() const { + return moved; + } + private: bool copied = false; bool moved = false; @@ -345,10 +345,10 @@ static_assert(_Constant_iterator>); // P2836R1 basic_const_iterator Should Follow Its Underlying Type's Convertibility constexpr void test_p2836r1() { { // Code from P2836R1 - std::vector v; - auto t = v | views::take_while([](int const x) { return x < 100; }); - auto f = [](std::vector::const_iterator) {}; - auto i2 = std::ranges::cbegin(t); + vector v; + auto t = v | views::take_while([](const int x) { return x < 100; }); + auto f = [](vector::const_iterator) {}; + auto i2 = ranges::cbegin(t); f(i2); // Error before P2836R1 }