|
1 | 1 | Consider how effortlessly we use **containers** and **iterators** from the Standard Template Library (STL) to traverse collections of data—whether it’s a `std::vector`, `std::set`, or `std::unordered_set`, despite them being very different containers, we can use the **same iteration logic without concerning ourselves with the details** of the containers and their iterators. This is "polymorphism", working with things that have very different details through an interface that represents an abstraction. Because it is the compiler the thing that resolves the abstract interface to the details of the specific types, we call this "compile-time" polymorphism.
|
2 | 2 |
|
3 |
| -This abstract interface principle that relieves us from having to know the details of the specific objects is also very valuable at *runtime*, especially if our application is going to produce objects that **we don't know what they are** before running the program. Other programming languages don't have as good compile-time polymorphism as we have in C++, thus, they focus exclusively on runtime polymorphism, to the point that for most of the Software Engineering community "polymorphism" simply means "runtime polymorphism". Furthermore, for them, polymorphism and **subclassing** are the same thing: the only practical way to get (runtime) polymorphism is via inheritance, and what we call "`virtual` overrides", and this is the fundamental mechanism of abstraction in those langauges, Object Oriented Interfaces. It turns out what we can still do that, and have the option of doing MUCH BETTER in C++. In the same way that we can achieve ease of programming with containers and iterators that are not related by inheritance, while at the same time getting optimal or nearly optimal performance, we can devise runtime polymorphism with the equivalent ease of programming and performance, efficiency, much, much better than through subclassing. This is what this presentation is about, ultimately, both working less and achieving objectively better performance. |
| 3 | +This abstract interface principle that relieves us from having to know the details of the specific objects is also very valuable at *runtime*, especially if our application is going to produce objects that **we don't know what they are** before running the program. Other programming languages don't have as good compile-time polymorphism as we have in C++, thus, they focus exclusively on runtime polymorphism, to the point that for most of the Software Engineering community "polymorphism" simply means "runtime polymorphism". Furthermore, for them, polymorphism and **subclassing** are the same thing: the only practical way to get (runtime) polymorphism is via inheritance, and what we call "`virtual` overrides", and this is the fundamental mechanism of abstraction in those languages, Object Oriented Interfaces. It turns out what we can still do that, and have the option of doing MUCH BETTER in C++. In the same way that we can achieve ease of programming with containers and iterators that are not related by inheritance, while at the same time getting optimal or nearly optimal performance, we can devise runtime polymorphism with the same ease of programming and far superior performance and efficiency —much better than through subclassing. This is what this presentation is about, ultimately, both working less and achieving objectively better performance. |
4 | 4 |
|
5 | 5 | It is not even difficult per se, you'll see in the solutions we have already coded that they are not that complicated, however, what we must do is to ground our work on **fundamentally superior principles** so that our path to do better is revealed.
|
6 | 6 |
|
7 |
| -What we want to achieve is **substitutability** as that means in the "Liskov Substitution Principle". |
| 7 | +What we aim to achieve is true **substitutability**, as defined by the Liskov Substitution Principle—allowing seamless replacement of types without compromising correctness or efficiency: |
8 | 8 |
|
| 9 | +**Substitutability**, as defined by the Liskov Substitution Principle (LSP), is the idea that objects of a given more abstract type, let's say, a "container", should be replaceable with objects of a **subtype**, a more specific or concrete type, let's say a `std::vector`, without altering the correctness of the program. In its essence, it ensures that any code working with an abstraction should not need to know the specific details of the underlying concrete implementation—it should "just work" regardless of the actual type used. Let us anticipate that we can achieve this by translating the amazing mechanism of abstraction of C++ to runtime, that's why we will "get ahead". |
9 | 10 |
|
| 11 | +Now, here’s the exciting part: we can translate powerful compile-time abstraction mechanisms, specific to C++, into the runtime domain. We will see how relatively easy it is to produce types with both "value semantics" and runtime polymorphism, something hugely popular languages such as Java and C# can't do at all. That’s how we "get ahead". |
10 | 12 |
|
11 | 13 | This works because **template-based polymorphism** lets the compiler generate type-specific code while preserving a common interface for iteration. The abstraction shields us from low-level details while the compiler resolves the specifics at compile time, leading to both flexibility and high performance.
|
12 | 14 |
|
|
0 commit comments