3 ms·
This is a blanket assertion. Why should useful semantics require generics? Why can't they come with simple fixed data structures? If you can provide a nice coun
by jstimpfle 5y ago
This is a blanket assertion. Why should useful semantics require generics? Why can't they come with simple fixed data structures? If you can provide a nice counterexample to the example that I gave, this would be more convincing.
Absent the absolute necessity of generics to support essential semantics, I'm probably in favour of a simpler generics-less version. I don't see why "more powerful libraries" get automatically easier to use. It could often be the opposite.
There is a tradition in some C++ subcultures where they try to cram in as many invariants as possible into types, concepts, templates, etc. at all costs. I tend to think that if all this heavy machinery is needed, the functionality might be too complicated from the start.
- ncmncm 5y agoIf you were writing a library, and a language feature made it possible to make your library easier to use safely, why would you not? You might as well say, "I don't see why a more expensive dinner has to be tastier." It is always easy to make libraries that are hard to use, in any language, but those do not become popular if there are better alternatives. We need generics because users have types that they need libraries to work with. Your own example, of an intrusively-linked list, illustrates this: without generics, you could not write a linked-list library component that would be usable for that. This is why C programs are crammed with so many custom one-off hash tables: You cannot code a useful hash table library in C. Libraries start simple, and accumulate your "heavy machinery" as they are made more useful and usable for their growing family of users. A library that lacks users does not.
- jstimpfle 5y agoIt's more like, "I don't see why a tastier dinner has to be more expensive". It's a tradeoff situation, and while I might be willing to buy a great $50+ meal from time to time instead of just a $20 one, I don't have any inclination to pay $1000 even if the meal is a tiny little bit better than the just-great one. It's a matter of tradeoffs. Library design is a balancing act. > We need generics because users have types that they need libraries to work with. This is right where I become sceptical. Most libraries shouldn't care for the user's types at all. They should expose their own types so you can work the library - not the other way around. Please provide an actual use case where the library has to "know" about the user's types (and please don't mention std::sort. It's as common an example as is "Dog :: Animal" examples to argue for class inheritance, and is just as irrelevant). > Your own example, of an intrusively-linked list, illustrates this: without generics, you could not write a linked-list library component that would be usable for that. As I mentioned, linked list can tangentially benefit from a very very thing generics layer on top of a fixed data structure implementation. The layer does nothing more than "instanciate" the types, but there is no code generated. But then again, the added convenience / safety is minimal, I once wrote a C++ implementation that I was quite happy with, and never used it. > This is why C programs are crammed with so many custom one-off hash tables There are probably not huge issues with a design like "HashTable ht = { .hash = &foo_key_hash, .equals = &foo_key_equals }" (if quick results are what you're after), but yes it is nice to have a few lines of type-safe wrap generated over some generic container interface. An alternative reason why you'll find a good amount of custom hashtables in C code bases is, I suppose, that there are a lot of different ways to implement hash tables. Also writing a little code here might not be so bad. I've had 1 use case for a "hash" table in 2021 (glyph hash table for a new iteration of my font rendering code) and I've gotten away without even implementing it - the for-loop I've written has never shown up in any performance profile. Considering that container data structures are probably the highest profile application for generics, I'm still not convinced that generics are needed in a systems programming language...
- ncmncm 5y agoYou miss the point. You can get more money for the dinner only if you deliver more. Your $20 meal delivers more than your $2 meal. If you can only deliver the $2 meal, you aren't getting $20 for it. I have already cited two separate examples, which you have studiously ignored. Look online and find them in their thousands. It is hard to find even one C++ library that is not made better by its ability to integrate with users' choices of types.
- jstimpfle 5y agoUpdated to not ignore your examples.
- tsimionescu 5y ago> This is right where I become sceptical. Most libraries shouldn't care for the user's types at all. They should expose their own types so you can work the library - not the other way around. This is an utterly bizarre statement. Should people convert collections of Xs from library 1 to other kinds of collections of Ys to work with library 2? A very basic use case that shows up all the time everywhere, especially in systems programming, is that I have an array of items and I want to pass it to some library. But, to work with an array, you need to know the size of elements of the array, so that arr[x] knows how to compute the address of x. There are exactly 3 ways to achieve this: 1. The library only accepts arrays of some specific type (e.g. int[]). If you have some other type, you have to find some way of converting to the type known in the library - in O(n) time. 2. The library expects arrays of some fixed-size type that can hold any value (e.g. void*[]). This typically adds huge overhead, since now the elements of the array are not together in memory, they are scattered all over the place; and the library must fetch them from memory before doing anything with them. 3. Generics - the library accepts T[], and can easily do sizeof(T) to know how to access arr[x]. Even qsort is actually an example of C's convoluted support for generic arrays: you're explicitly passing the array base and its type (the number of bytes) to qsort. C's extremely basic type system anyway essentially identifies types with byte sizes in practice, so it's not obvious that qsort works like this (and of course, it's less safe, since instead of passing an int, you have to pass void* + sizeof(int), potentially getting them mixed up).
- dmitriid 5y ago> This is a blanket assertion. Why should useful semantics require generics? Why can't they come with simple fixed data structures? What do you mean by "fixed data structures"? > If you can provide a nice counterexample to the example that I gave I may be missing somehing but I don't understand your example. The idea of a list is that we want it to hold any data, so the API to a list by necessity becomes generic. Unless you cas everything to void*. --- I have another counterexample from userspace. Our internal APIs all use the same converntions which make working with them predictable and same from any language. An API returns: { result: [a list of data], nextPageToken: } Different APIs will of course have different data. Some API will return a list of contracts. Another API will retur a list of media. A third API will... etc. I had the misfortune of working with these APIs in Go before generics. Welcome to copy-pasting code that deals with this. Or cast from interface{}/void* to proper data in runtime. Any sane language of course lets you write something like GetAllData<T>()
- elb2020 5y agoIf std::vector, std::array or std::unique_ptr could somehow have been implemented better without the use of templates in the C++ standard library, I think you'll find that they would have been implemented that way. I don't know what you mean by "essential semantics", but the fact remains, as ncmncm says, that templates is the feature that allows new types of type safe generic abstractions to be built and added to the arsenal of C++ programmers. It's the feature that, most of all, has kept the C++ language alive and thriving over the past 20 years, in my opinion. Without it, the language would probably be dead.