Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<ranges>: Fix views::reverse for ranges::reverse_view lvalues #2313

Merged
merged 3 commits into from
Nov 3, 2021

Conversation

cpplearner
Copy link
Contributor

Fixes #2312

@cpplearner cpplearner requested a review from a team as a code owner November 1, 2021 16:52
@@ -4167,24 +4167,24 @@ namespace ranges {

template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (bidirectional_range<_Rng>) {
Copy link
Contributor Author

@cpplearner cpplearner Nov 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the bidirectional_range<_Rng> check because

  1. [range.reverse.overview]/2 does not seem to have this
  2. this breaks the following (contrived) code:
#include <ranges>
#include <iterator>
#include <istream>

using namespace std::ranges;
using namespace std::views;

struct weird : view_interface<weird> {
    int* begin();
    int* end();
    std::istreambuf_iterator<char> begin() const;
    std::istreambuf_iterator<char> end() const;
};

int main() {
    const auto v1 = weird{};
    auto v2 = reverse(v1); // rejected by MSVC STL w/o this patch, accepted by libstdc++
    auto v3 = reverse_view{v1}; // accepted by MSVC STL and libstdc++
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have been thinking this was bidirectional_range<remove_cvref_t<_Rng>>? Even if that is correct, checking it first seems to make the first 3 cases more expensive and has no effect on the reverse_view case. I'll put this in the "I don't know what I was thinking, but I know I was wrong" bucket. (No change requested.)

@CaseyCarter CaseyCarter added the bug Something isn't working label Nov 1, 2021
tests/std/tests/P0896R4_views_reverse/test.cpp Outdated Show resolved Hide resolved
@@ -4167,24 +4167,24 @@ namespace ranges {

template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (bidirectional_range<_Rng>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have been thinking this was bidirectional_range<remove_cvref_t<_Rng>>? Even if that is correct, checking it first seems to make the first 3 cases more expensive and has no effect on the reverse_view case. I'll put this in the "I don't know what I was thinking, but I know I was wrong" bucket. (No change requested.)

@CaseyCarter CaseyCarter added the ranges C++20/23 ranges label Nov 1, 2021
cpplearner and others added 2 commits November 2, 2021 01:25
@StephanTLavavej StephanTLavavej changed the title <ranges>: fix GH-2312 <ranges>: Fix views::reverse for ranges::reverse_view lvalues Nov 1, 2021
@StephanTLavavej
Copy link
Member

Updated title so we can easily see what this PR does.

@@ -317,6 +317,12 @@ using move_only_view = test::range<Category, const int, test::Sized{is_random},
IsCommon, test::CanCompare{derived_from<Category, forward_iterator_tag>},
test::ProxyRef{!derived_from<Category, contiguous_iterator_tag>}, test::CanView::yes, test::Copyability::move_only>;

void test_gh2312() { // COMPILE-ONLY
using X = ranges::iota_view<int, int>;
ranges::reverse_view<X> view;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes close to shadowing ranges::view:

STL/stl/inc/xutility

Lines 2701 to 2702 in ee5a216

template <class _Ty>
concept view = range<_Ty> && movable<_Ty> && enable_view<_Ty>;

In general, I recommend avoiding top-level Standard identifiers. This improves codebase searchability, and makes tests quickly scannable by humans (e.g. if I see vector or string in a test, I can assume I'm looking at the Standard one).

However, as this doesn't actually shadow, no change requested - I think this is sufficiently small that a rename is not worth resetting testing.

@StephanTLavavej StephanTLavavej self-assigned this Nov 2, 2021
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit b2aa34d into microsoft:main Nov 3, 2021
@StephanTLavavej
Copy link
Member

Thanks for fixing this ranges bug!

(I reversed this message twice, but you can't tell the difference now! 😹 🤪 🎉)

@cpplearner cpplearner deleted the gh-2312 branch November 3, 2021 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ranges C++20/23 ranges
Projects
None yet
Development

Successfully merging this pull request may close these issues.

<ranges>: using views::reverse on ranges::reverse_view lvalue is broken
4 participants