3 ms·
Some comments on your proposed additions (my other comments were about the proposed reductions): - I don't think .NET-style generics can be implemented in a st
by phaedrus 16y ago
Some comments on your proposed additions (my other comments were about the proposed reductions):
- I don't think .NET-style generics can be implemented in a statically typed language that doesn't have a common base class (e.g. everything derives from class Object). This is an oversimplification to say this but at some level generics are implemented as syntatic sugar for typecasts between Object and the type parameter type. If you want generics instead of templates, a lot of C#'s design gets pulled in along for the ride. Nothing wrong with that (C# is a fine language), just as long as you understand it will happen and why. But also be aware that it means you will never be able to make a generic array class that performs as fast as a C++ STL vector does - which violates your own starting criteria, that it has to be as fast as C++ to succeed.
- Most of the time I wish pass-by-reference were implicit, but pass by value has some special consequences in C++ that make it unlike many other languages. I was able to write a class that does fast bit-twiddling on itself, with its internal representation being an integer, and the entire thing was no more expensive in memory or speed than C functions bit twiddling on an int. So I was able to get abstraction and raw speed with no compromises. That's a rare use case, but I think it is illustrative of why pass by value is in C++ - you don't need it most of the time, but when you need it, you really need it.
As for not being able to reseat a reference, I found that frustating too until I started learning LLVM and about SSA (static single assignment). The common answer to why you can't reseat a C++ reference is just that it has something to do with compiler optimizations. That common answer is too weak; it has EVERYTHING to do with how the compiler optimizes the code. Basically, if you're asking why can't I reseat a reference, you don't understand what a reference is. But it's not your fault: what you really don't understand is that C++ uses the word reference to refer to a thing that is not exactly like references as used in other languages. I used to think a reference was syntactic sugar for a pointer; that's not quite true. A C++ reference literally IS the object; it's just converted to a pointer during the process of a function call. The reason you can't reseat the reference is that if you could the static analysis of the program becomes immeasurably harder and later in the code the compiler cannot be absolutely sure that it knows what the reference really refers too.
In a way, not being able to reseat a C++ reference is a lot like not being able to assign to a constant defined by a macro or not being able to assign a new address to a function at runtime. It's part of a class of things that happen at a stage before runtime, and to change the system so that it would be possible would require introducing a level of indirection.
- JoachimSchipper 16y agoTo the best of my knowledge, current C compilers typically convert C programs (which obviously don't have a concept of a reference) into SSA form as one of the first steps after parsing. It's, to me, not obvious that this couldn't be done with C++ references either. (Yes, this would make writing a decent C++ compiler harder; but it's already so monstrously hard that this optimization, which is already in all major compilers anyway, would be a significant additional burden.)
- saucetenuto 16y ago> This is an oversimplification to say this but at some level generics are implemented as syntatic sugar for typecasts between Object and the type parameter type. This is not true. Java generics work this way (google "type erasure"), but C# generics are implemented with specialized code, so that e.g. List<int>.Add has its own IL implementation distinct from the one for List<Bitmap>.Add. This lets the JIT do type-specific optimizations, like not having to box the ints in a List<int>. The specialization code also tries to share code in cases where the type parameters don't matter (e.g. so that you don't have a million identical implementations of List.Count hanging around).
- jaen 16y agoGenerics requiring type casts and a common base class is Java type-erasure braindeadness. CLR (.NET) generics compile separate code for each value type parameter, so you can have eg. vectors of structs, with the same performance as in C++. (for reference types, it uses the same code with an additional hidden "generic context" parameter, but that's an implementation detail). CLR has pass-by-value too, and although older versions of the MS.NET JIT did not inline such functions, the current version should have performance similar to C++. Unfortunately, few programmers know how to get the maximum performance out of the CLR. About not being to able to reassign references in C++ - the main reason is probably because that would require a separate operator, since assigning to a reference calls operator= on the class. C++ has subtle interactions in many areas of the language, especially operator overloading, allowing you to override even assignment. If C++ can not do something apparently simple, there is probably a good reason for that, only obvious to those who know the spec inside out.