ericniebler / range-v3

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

Error when using function return value directly #1813

Open icedream2linxi opened 8 months ago

icedream2linxi commented 8 months ago

version: 0.12.0 compiler: Visual Studio 2022 x64

code:

#include <vector>
#include <range/v3/view.hpp>
#include <range/v3/range.hpp>
namespace rv = ranges::views;

std::vector<int> getAllItems()
{
    return {};
}

int main()
{
    std::vector<int> allItems;
    auto tt = getAllItems()
        | rv::filter(
            [](auto item)
            {
                return item % 2 == 1;
            })
        | ranges::to<std::vector<int>>();
    return 0;
}

error logs:

Build started at 16:43...
1>------ Build started: Project: ConsoleApplication_141_03, Configuration: Debug x64 ------
1>ConsoleApplication_141_03.cpp
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2280: 'std::vector<int,std::allocator<int>> ranges::views::view_closure_base_ns::operator |<std::vector<int,std::allocator<int>>,ranges::detail::bind_back_fn_<ranges::views::filter_base_fn,main::<lambda_1>>>(Rng &&,const ranges::views::view_closure<ranges::detail::bind_back_fn_<ranges::views::filter_base_fn,main::<lambda_1>>> &)': attempting to reference a deleted function
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2280:         with
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2280:         [
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2280:             Rng=std::vector<int,std::allocator<int>>
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2280:         ]
1>C:\Users\xxx\.conan\data\range-v3\0.12.0\_\_\package\5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9\include\range\v3\view\view.hpp(127,13):
1>see declaration of 'ranges::views::view_closure_base_ns::operator |'
1>F:\TestProject\ConsoleApplication_141_03\ConsoleApplication_141_03\ConsoleApplication_141_03.cpp(15,9): error C2088: '|': illegal for class
1>Done building project "ConsoleApplication_141_03.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 16:43 and took 01.702 seconds ==========
Arghnews commented 7 months ago

This is intended behaviour

Unfortunately, it looks like msvc doesn't print the helpful stuff that gcc or clang would in the error message:

/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/view.hpp:127:13: note: candidate function [with Rng = std::vector<int>, ViewFn = ranges::detail::bind_back_fn_<ranges::views::filter_base_fn, (lambda at <source>:16:13)>] has been explicitly deleted
  127 |             operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********

And the referenced code section:

            template<typename Rng, typename ViewFn>         // **************************
            friend constexpr auto                           // **************************
            operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
                                                            // **** IF YOUR COMPILE *****
                -> CPP_broken_friend_ret(Rng)(              // ****** BREAKS HERE *******
                    requires range<Rng> &&                  // **************************
                    (!viewable_range<Rng>)) = delete;       // **************************
            // *    When piping a range into an adaptor, the range must satisfy the     *
            // *    "viewable_range" concept. A range is viewable when either or both   *
            // *    of these things are true:                                           *
            // *      - The range is an lvalue (not a temporary object), OR             *
            // *      - The range is a view (not a container).                          *
            // **************************************************************************

See https://gcc.godbolt.org/z/s58o7bjqT

getAllItems() returns an rvalue std::vector, and rv::filter is a view, ie. non owning

The issue with this code working would be where the rvalue vector would live, what would own it - views are lightweight and don't own containers like this (except cache1 AFAIK) so the filter view can't. Nothing can. | ranges::to<std::vector<int>>(); can be removed and you'll get the same error

As you've alluded to in your code snippet, and the above compile message says, a fix here is to use an lvalue instead

stribor14 commented 1 month ago

In c++20 this works because of p2415 as mentioned in #1725