As a revolutionary standard in C++ history, C++20 has proposed lots of features that would change the way how people programming with C++. And the <ranges> header and pipes concept are one of them.

To be straightforward, let’s look at an example using the pipes in a for loop:

using namespace std::ranges;
 
auto square = [](int x) -> int { return x * x; };
auto valid = [](int x) -> bool { return x % 4 == 0; };
 
// Lazy evaluation
for (int i : views::iota(1) | views::transform(square) | views::filter(valid) | views::take(5)) {
  std::cout << i << std::endl;
}

The result of this code snippet is to checkout the first 5 number whose square are divisible by 4. The std::views:iota(1) will generate a sequence of number starting from 1 and increasing by 1. The sequence is floating in a pipe and fed into next two gates: std:views:transform and std::views::filter, the former transforms the input into it’s square and the letter only allows elements which are valid judged by its parameter.

Note that std::views::iota gives out the sequence at runtime (a.k.a. lazy evaluation), so std::views::take should be used to truncate the sequence, avoiding endless loop.

As we can see, this new style of code is more concise and acting more like functional programming.

Another example:

std::string s{"LOL, love from [email protected]!"};
bool after_at = false;
 
for (auto c : s | views::filter([&after_at](char c) {
                bool ret = std::isalpha(c) && std::islower(c) && after_at;
                after_at = after_at || c == '@';
                return ret;
})) {
  std::cout << c;
}
 
// Origin string not changed
std::cout << std::endl << s << std::endl;

This loop outputs lower case letters appeared after @ symbol ("haungxtcn" in this case). In pipes, we can define a more complex lambda expression as in other place.

People have been complaining all the time that there is no elegant way in C++ to split a string. With the help of pipes, we can easily do that:

std::string s{"LOL, love from [email protected]!"};
// Split for string
for (auto word : s | std::views::split(' ')) {
  std::cout << " -> ";
  for (auto c : word | std::views::transform([](auto c) -> char { return std::toupper(c); })) {
    std::cout << c;
  }
}
 
std::cout << std::endl;

References

  1. (Chinese) https://tjsw.medium.com/%E6%BD%AE-c-20-ranges-views-%E4%BD%BF%E7%94%A8-stl-%E7%9A%84%E5%85%A8%E6%96%B0%E5%A7%BF%E5%8B%A2-8007777a8da6