4 ms·
I have to admit, the STL - and more generally templates - in C++ are very perplexing to someone that has a strong background in a language with a more complete
by Alupis 6y ago
I have to admit, the STL - and more generally templates - in C++ are very perplexing to someone that has a strong background in a language with a more complete generics implementation (ie, Java or C#).
The very fact that templates are not classes, specifically not base classes for all derived variants of the template is perplexing and, in my opinion, a major swing and miss for a language that seems to pride itself on having everything including the kitchen sink.
I've read the reasons behind why templates do not share any inheritance with derived classes, and it makes sense within the context of how C++ and more specifically the compiler works... but it limits the usefulness of templates past mere containers.
- dragontamer 6y ago> but it limits the usefulness of templates past mere containers. Your post (specifically, your conclusion) makes me think that you are fundamentally mistaken about how to use templates. Template metaprogramming is an old-trick at this point, with a huge variety of applications in C++. But even if you ignore Template metaprogramming (which many argue is too difficult to understand...), bog-standard C++ techniques like CRTP (Curiously Recurring Template Pattern) shows how useful templates can be outside of containers. https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern https://en.wikipedia.org/wiki/Curiously_recurring_template_p... --------- C++ templates are extremely different beasts than generics. Templates are closer to a meta-language than a language feature. They hold important roles in optimization... specifically allowing you to convert "runtime code" into "compile time code" in a huge class of problems. CRTP is a great example of retaining OOP-style polymorphism while compiling down into highly efficient non-virtual calls... with practical applications into GUI frameworks, video games and more. And its only made possible due to templates.
- Alupis 6y agoInteresting, I've never heard of CRTP and will need to read up on it. I do "get it" that templates are not generics... there's just a lot of gotchas for someone assuming generics, err - templates are similar to other languages. Like the difficulty in nesting templates in templates...
- dragontamer 6y agoEven in the use of "containers", generics are the complete opposite of how to use templates. Java / C#'s concept of "Everything derives from Object" is outright rejected in C++. Templates are part of this culture: how can we provide extendibility when nothing is an Object? Well, look at iterators in C++. All C++ iterators extend from all collections WITHOUT the use of OOP-derivations. That's thanks to the magic of Templates. ------ What's going on? C++ templates allow the creation of new iterator classes. It invokes the compile-time language to create a new class at compile time. In Java / C#: vector<MyClass> is the same old vector as all other vectors. In C++: vector<MyClass> is a custom-made, completely separate class from all other vectors. vector<MyClass>::iterator is a 2nd, custom-made completely separate class from all other iterators. And yet, all of these different classes can be used the same, thanks to the use of auto, or other compile-time structures in C++.
- Alupis 6y agoGetting Java's generics out of your head when doing C++ is definitely a challenge. It's just so disappointing you cannot do something like: void myFunc(List<? extends MyDataContainer<?>> list); Instead you end up with a base class MyDataContiner and then manually extending it with something like MyDataContinerInt or MyDataContinerLong etc... C++ templates may be very powerful, but limitations like this feel out of place in a language as bloated as C++ already is... Admittedly, I still have much to learn about C++. It's been quite an experience, frustrating at times, learning this language.
- aw1621107 6y agoI think you can get something similar now with C++20 concepts? template<typename T, typename U> void my_func(std::vector<T>* vec) requires std::derived_from<T, my_data_container<U>>; (Probably mangled something, but the idea is there) Without concepts, you're left with SINFAE: template<typename T, typename U, typename = std::enable_if_t<std::is_base_of_v<my_data_container<U>, T>>> void my_func(std::vector<T>* vec); or just a regular function and a hope that anything wrong will be caught by the compiler: template<typename T, typename U> void my_func(std::vector<T>* vec) { // use my_data_container<U> somewhere and hope things blow up if something is wrong // Not 100% sure this is allowed, but something similar should be at least }
- aw1621107 6y ago> The very fact that templates are not classes, specifically not base classes for all derived variants of the template is perplexing I'm a little confused at what you're trying to get at here. What do you want to do that needs such a thing? What is the equivalent Java/C# code you have in mind? > but it limits the usefulness of templates past mere containers. What kinds of uses did you have in mind for a "template base class"?
- Alupis 6y agoExtend a template and specialize it for some type. Extend the template again and specialize it for some other type. The two resulting derived classes are not the same, and you cannot have a function that accepts the base template with a wild card type and pass both types into it. In Java, you can do: void myFunc(List<?> list); and all List objects with any type can be accepted by this method, in addition any class that extended List can also be accepted into this method, such as ArrayList<?> or whatever. As far as I've seen, this is impossible in C++, unfortunately.
- aw1621107 6y agoWhy not template<typename T> void my_func(std::vector<T>& vec); ? The reference (or use a pointer, if you want) ensures that derived types can be passed, and the template allows for any parameterization to be used.
- deleted 6y ago[deleted]
- deleted 6y ago[deleted]
- slavik81 6y agoAs a C++ developer, I see things entirely the other way. Java templates are much less powerful than C++ templates. In Java, templates were basically just a convenient way to do type erasure. That's better than nothing, but the inability to specialize templates makes them quite limited. In C++, you can define a common base class if you need one, but being able to optimize based on the template type is very useful. Function templates are great for writing concise, efficient math that handles half-precision, single-precision, double-precision, single-precision complex numbers and double-precision complex numbers (and more) with minimal duplication. Templates are also what make interfaces like std::format efficient and easy to use.