Pipeable
Pipeable
is perhaps a rather controversial way of programming C++.
There is pipeable in Boost: pipeable - Boost.HigherOrderFunctions 0.6 documentation - master. It is a part of the hof library
The HOF library stands for Higher-order functions for C++, and its author Paul Fultz II is also a celebrity. There are two Posts in his blog related to the topic of this article.
Similarly, there are Extension methods in Boost. methods).
Fundamentals
We note that the origin of Pipeable programming comes from pipe operations in the OS Shell, e.g.
|
|
In particular, when the C++ operator ’ ’ (logical or) can also be overloaded, everything seems to fall into place.
The key C++ idea is to do ’ ’ operator overloading as well as ‘()’ operator overloading.
The user class F can then have the ability to operate with ‘|’ under the pipe_closure decoration (provided that F also implements the ‘()’ operator overload.
Then the pipeable tandem operation looks like this.
Note that the ‘()’ operator accepts the generic class T as an input, so that it receives the lhs element forwarded by pip_closure<F>::operator |
, the left-hand operand of the " " operator. In this way, the result of the lhs expression is piped to the rhs operand in operator ()<T>()
, thus completing the pipeline operation.
Slightly improved
Obviously this idea can be further embellished.
|
|
Then, to be able to have a more elegant presentation of.
|
|
The above pipeable class and piped(…) are from Functional pipeline in C++11 - Victor Laskin’s Blog, his implementation is more meaningful, so we like it a bit more.
ACK: the following image is from his blog
Paul Fultz II’s motivation is more of a priority, I just never really use boost, it’s too large and complete to be used in engineering at all. I prefer something relatively lightweight, yet relatively complete.
If you’re interested in Paul Fultz II’s implementation, in addition to boost::hof::pipeable, he also made the open source Linq: pfultz2/Linq: Linq for list comprehension in C++. This is a C++ implementation of the C# Linq technology, which is amazing and crazy.
successor
Here is the extended reading time.
ranges
Of course, it is also important to mention the std::ranges range library, which is one of the changes brought by C++20, but the C++20 specification has not been released for long enough for engineering applications to be realistic.
ranges also has an incubation project of the same name ericniebler/range-v3: Range library for C++14/17/20, basis for C++20’s std::ranges, which can be used if you don’t want to enable c++20 right away, requires clang 3.6+ or gcc 4.9.1, so older projects say no pressure.
In general, ranges provide a filtering tool that allows you to filter, sort, mapreduce, etc. on top of a pipeline filter.
But range v3 is also a mixed bag.
How to understand the scope library
In fact, this guy is just as inexplicable as other terms like protocol, concept, etc. Do you know what a concept is?
Do you know what a concept is? iykyk, I’m a real Chinese person who doesn’t have any idea about concepts.
However, C++20’s std::concept is a weird thing.
Their actual meanings have to go into the etymology of the English roots, so they are hard for Chinese people to understand intuitively.
Here, let’s ignore the ranges etymology and use std::ranges::view to understand it. In other words, a ranges library is a cross-section of a set, a view that can be observed, and then a view that can be multiplied or added, or the mean can be calculated, or other aggregation operations can be done, or sorting can be done, or map reduce can be done.
The question of what you can do is not a question of ranges, but how you are going to do it on the view provided by ranges. So to make good use of the ranges library, you should have a good understanding of functional programming. For those who have an understanding of C# Linq techniques, RxJava can easily understand the core of std::ranges.
Use
As for using ranges, refer to the examples they provide.
|
|
It’s hard to say if this is progress.
Other Languages
Kotlin
|
|
Kotlin would look better if it were RxJava
If Kotlin didn’t always come with a JVM, I would be completely and utterly bored.
Of course, Rx also has a c++ version, RxCpp, which tastes like this.
|
|
What can only be said, bad is bad in […] (…) { … } is an outrageous and rather unattractive lambda function body. When compared to kotlin’s lambda, it’s a retreat.
In fact, this has been the case with all the changes since C++11, creating a lot of weird and unintuitive stuff. I’m afraid it would be dead if not for some new goodies and history.
About the controversy I mentioned
First of all on the one hand, C++ anonymous functions are in terrible shape. See C++0x lambdas suck, C++ lambda ugly, etc.
On the other hand, we have to see that this is also historical, not to mention that C++’s functional style originally had its own style, and ranges of things like standards came too late, too many different implementations caused confusion, and standards, well, always late.
With C# closures, Java 8 closures, and Kotlin closures in the foreground, C++ can’t win this battle under the preconceptions.
About Extension Method
This concept, is part of Protocol-oriented Progamming (PPP).
Swift
In Swift language, you can extend any class by means of Protocol (Extensions). It behaves somewhat like this.
|
|
Another example, adding a reverse() method to the String class (note: String has a native method reversed()).
The examples above do not make use of protocol constraints, so they only show the ability to extend existing classes. You can extend a generic class that meets a specific protocol constraint, thus giving that group of generic classes an additional method. This is too large to expand on here.
Kotlin
Kotlin provides the means for Extension Function, which can be considered a disruptive and innovative design for Java.
This time the example is slightly different.
This adds the reverseCaseOfString() method to the String class, which is no different from String.length().
|
|
Those of you who are mobile developers should be familiar with this capability of Swift and Kotlin.
In C++
I’ve been studying and dreaming for a long time (several years, spanning a decade) to be able to do the same thing in C++. But even at c++23 this is still not possible.
As for creating an equivalent C++ class library, the conclusion, after many failed attempts, is that it is still not possible.
A less-than-perfect way to extend the functionality of existing classes through C++ is through the Decorator Pattern, which is the most standardized solution, but is badly shaped and cumbersome:
|
|
Using the decorate pattern, you can either decorate the implementation of existing methods or add new ones (CIrcle.Resize()), but you need to display the construction to the decorator class to do so (ColoredShape colored_shape("red", &circle)
). An improvement would be to use the template class for mixin, but that would be a limited improvement.