Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using '|' (pipe) operator with std::views does not compile

Tags:

c++

std

c++20

After a career diversion, I am trying to get up to speed with std::views (and functional programming in general). I am using the '|' (pipe) operator with std::views::filter on a vector, and I am puzzled why some code structures compile and others don't.

This code creates a vector of vectors of int, then filters them by sum. I've commented the three statements that are confusing me, the first two of which compile and the third doesn't.

Compilation error is:

'|': no operator found which takes a left-hand operand of type 'std::vector<std::vector<int,std::allocator<int>>,std::allocator<std::vector<int,std::allocator<int>>>>' (or there is no acceptable conversion)  

(Using MSVC19, compiled with /std:c++latest)

I am puzzled as to why this doesn't compile while (2) especially does?

#include <vector>
#include <numeric>
#include <ranges>

template<typename T>
auto buildMultiples(const std::vector<T>& base)
{
    std::vector<std::vector<T>> vRet;
    for(T n= 1; n <= 5; n++)
    {
        auto v = base;
        for (auto& m : v) m *= n;
        vRet.push_back(v);
    }
    return vRet;
}

template<typename T>
struct sumGreaterThan
{
    T _limit{ 0 };

    auto operator()(const std::vector<T>& v) {return std::accumulate(v.cbegin(), v.cend(), 0) > _limit;}
};
   
int main()
{
    using namespace std;
    vector<int> nums{1,2,3,4,5,6,7,8,9};

    auto mults = buildMultiples(nums);

    for (auto& m : buildMultiples(nums)) {} //1. Compiles

    sumGreaterThan sumFilter{ 10 };
    
    auto vecs = buildMultiples(nums);
    for (auto& m : vecs | views::filter(sumFilter)) {} //2. Compiles

    for (auto& m : buildMultiples(nums) | views::filter(sumFilter)) {} //3. Compilation Error!!

    for (auto vecs = buildMultiples(nums); auto & m : vecs | views::filter(sumFilter)) {} // 4. Compiles. Thanks @Aryter
}
like image 667
DS_London Avatar asked Dec 01 '21 21:12

DS_London


People also ask

How to use pipe operator in Linux?

As the pipe is like a redirection operator, we can use it in different commands. Some of the options are mentioned below : 1) grep -I filename | sort: In this, the grep result will be fetched from the filename and will act as an input to the sort command, and the sort command will sort the data in default mode.

What is the pipe command in Linux?

The pipe command syntax is straightforward. As the pipe is like a redirection operator, we can use it in different commands. Some of the options are mentioned below :

How to implement named pipes in a network?

In .NET, you implement named pipes by using the NamedPipeServerStream and NamedPipeClientStream classes. See How to: Use Named Pipes for Network Interprocess Communication.

What is the use of a pipe in net?

Pipe Operations in .NET. Pipes provide a means for interprocess communication. There are two types of pipes: Anonymous pipes. Anonymous pipes provide interprocess communication on a local computer. Anonymous pipes require less overhead than named pipes but offer limited services. Anonymous pipes are one-way and cannot be used over a network.


Video Answer


1 Answers

This is passing an lvalue vector into filter:

vecs | views::filter(sumFilter)

whereas this is passing an rvalue vector into filter:

buildMultiples(nums) | views::filter(sumFilter)

The current rule, which compilers implement, is that range adaptor pipelines cannot take rvalue non-view ranges (like vector, string, etc.). This is because the pipeline itself is non-owning (views were non-owning), and exists as a safety mechanism to prevent dangling.

The new rule, recently adopted as a defect, would allow this could and would cause filter to own the result of buildMultiples (this is P2415), but compilers don't implement it quite yet. With this change, your other version would also have compiled.

So for now, you will have to keep writing it this way (as you are already doing):

auto vecs = buildMultiples(nums);
for (auto& m : vecs | views::filter(sumFilter)) { ... }
like image 128
Barry Avatar answered Oct 26 '22 16:10

Barry