There is a big problem in C++ and I want to bring it into awareness and *maybe* propose a solution to it.
Today there is a war going on between static polymorphism and dynamic polymorphism.
For example, consider the following piece of code:
void print_str(std::ofstream & os, std::string const& str) {
os << str;
}
(I'm not good at giving concrete examples)
It simply writes a std::string to an std::ofstream.
Why is it that this operation involves a virtual function call? I'm using concrete types, and I didn't even ask for polymorphism of any kind.
Why is it that I'm not given a choice of whether or not I want dynamic polymorphism, but when using std::string for example I can only use
static polymorphism? Why is it chosen for me by the class writer. Surely, he/she doesn't know what my specific needs are.
C++ is about giving the user as much choice as possible to do what suits him/her.
I feel like the choice has been made for me by someone who doesn't know what suits me in my specific situation.
Let's look at it from a class writer's point of view:
I'm writing a new class and I want some sort of polymorphism. Do I need static or dynamic polymorphism? And for which method/s?
No one can answer this question because it depends on the case.
That is exactly why you should be able to choose when the case arrives.
What I think is the solution to the problem:
In my opinion the solution is to have some sort of std::any class that receives a concept as its
template parameter and then provides us with type erasure based on that concept.
Much like std::function can provide a single interface to all functor types based on signature,
std::any<std::Ostream> would be able to provide a single dynamic interface to all std::Ostream models.
So I have a choice between the code example above and this:
template <std::ForwardRange<char> Str>
void print_name(std::any<std::Ostream> & os, Str const& str) {
os << str;
}
The first code example would use static polymorphism whereas this one would use dynamic polymorphism for os and static for str.
Just as I asked from the compiler.
This way we can get dynamic/static polymorphism when we explicitly ask for it.
By the way, std::any<std::Ostream> would also be a model of std::Ostream which makes this solution very flexible and
makes this a whole lot more exciting in my opinion.
This solution is very similar to a proposed Boost library called Boost.TypeErasure.
It is a very interesting and exciting library in my opinion, but I think that it needs to be able to work with core-language concepts in order
to change the way we write code for the better.
C++ will be full of types and concepts. Types would merely be implementations of generic concepts.
C++ would be totally polymorphic, either by static or dynamic polymorphism based on the case at hand.
Concepts would not be limited to templates anymore. They would be the best uncompromising way for creating interfaces.
I'm very excited for the future of C++ and I think this might be it.
Please let me know what you think.