ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.06k stars 437 forks source link

Unexpected copy of other container in zip_view #1673

Closed ingo-loehken closed 2 years ago

ingo-loehken commented 2 years ago

If a temporary container is combined with a non temporary container inside a zip_view, it tries to copy the non temporary container. This is unexpected.

struct XXXX
{
    std::unique_ptr<std::array<int, 2>> m{};

    friend decltype(auto) begin(XXXX& x)
    {
        return std::begin(*x.m);
    }

    friend decltype(auto) begin(XXXX const& x)
    {
        return std::begin(*x.m);
    }

    friend decltype(auto) end(XXXX& x)
    {
        return std::end(*x.m);
    }

    friend decltype(auto) end(XXXX const& x)
    {
        return std::end(*x.m);
    }
};

namespace ranges::ext
{
    template<typename T>
    struct enable_view;

    template <>
    struct enable_view<XXXX>
        :std::true_type
    {
    };
}

XXXX const z;

for(auto const& [x, y] : ranges::zip_view(z, std::array{1,2})) // fails to compile, because tries to copy z
{
    // ...
}

This happens with the latest release (0.11.0) under msvc 16.11.5 (visual studio 2019).

ericniebler commented 2 years ago

In range-v3, views are required to be copy constructible. Move only views were added to std::ranges during standardization, and range-v3 hasn't kept up.

ingo-loehken commented 2 years ago

But placing the array in a named var, elides the copy ctor call.

std::array const xs{1,2};
XXXX const ys;

for(auto const& [x, y] : ranges::zip_view(xs, ys)) // works, no copy for ys required
{
    // ...
}
ericniebler commented 2 years ago

Yes, because in that case the view captures the stay by reference. No copies.

ingo-loehken commented 2 years ago

And if any rvalue is found, all args, and therefore also non copyable ys, are copied into zip_view ?