4 ms·
Virtual generic functions do make sense and many languages allow them. The problem is C++ implements them by compile-time macro expansion (called templates), wh
by pkolaczk 13y ago
Virtual generic functions do make sense and many languages allow them. The problem is C++ implements them by compile-time macro expansion (called templates), which renders them impossible.
Template types are also not really first-class members of the type system. The compiler can't really reason about them, it only type-checks them after expansion, when all the genericity disappears. This is completely different than the fail-fast approach in Haskell or even Java, where the code is type-checked at the generic level.
Don't get me wrong - templates is an awesome, extremely powerful feature of C++, but it doesn't play well with the rest of the language, and really feels tacked-on.
- pandaman 13y agoSure, generic functions are awesome when you don't care about performance. This is why C++ does not have them. If you knew nothing about C++ and somebody told you "here, we have a language with zero run-time overhead, can you guess if we managed to implement generic functions?" what would you say? Function templates are not generic functions. Same as template classes are not types. They play really well with the rest of C++ but I agree, not so well with the rest of Java or Haskell :) This is the major problem people nowadays have with C++ - they learn some "practical" high-level language in school (usually riddled with random stuff, judging by how much people here are pissed with my mentioning of PHP) and try to think about C++ in concepts of such a language. Then blame C++ for not being their favorite language. Don't get me wrong. I am quite happy with this making my skills very rare and expensive, giving me both job security and decent compensation. I also want to thank all the people spreading the "C++ is complex hodgepodge of completely random things so it's impossible to learn" idea :)
- cousin_it 13y agoI guess it's a matter of taste. Almost every time I get puzzled by some design decision in C++, it makes sense at first but then falls apart on closer inspection. The most recent example amused me so much that I wrote a blog post about it: http://slepnev.blogspot.ch/2013/07/printing-int-in-c.html http://slepnev.blogspot.ch/2013/07/printing-int-in-c.html. My experience with Haskell so far has been the opposite, design decisions make no sense at first but then turn out to be really smart.
- pandaman 13y agoC++ library is not something that is supposed to be very useful, it's something that is supposed to be available. I, for one, never used that library in my 15 years of professional programming. Even though the library is covered by the same standard as the language it's not a part of the language and, in practice, is not even available all the time.
- pkolaczk 13y ago@pandaman: Just a minor nitpick about the statement that C++ library is not a part of the language: How come 'new' (builtin language operator, and reserverd keyword) can throw 'std::bad_alloc' (library construct) then? ;)
- pandaman 13y agoNew itself does not throw, the allocation function does. Nobody makes you use the library allocation functions. A better nitpick would be dynamic_cast throwing under some conditions. But then, how does it make iostreams the part of the language? There is just a typedef in the std namespace that aliases the type for some optional, compiler specific, data.
- pkolaczk 13y ago@cousin_it: I have exactly the same feeling about C++ and Haskell. Another feature of this kind is inability to do virtual calls from constructors / destructors. Sure, the explanation makes perfect sense and leaves you with a feeling that C++ got it right and the rest of the world got it wrong. C++ protects you from accessing not-fully initialized object, awesome isn't it? Unfortunately it gets in the way when using factory methods (which are perfrctly ok to be called from the constructor in other languages) and is a source of subtle bugs.
- pkolaczk 13y agoGeneric functions like in Java/C# can be implemented efficiently and with zero overhead. There is nothing that prevents a JIT compiler to generate several versions of the code optimised for different types at runtime, exactly like C++ does at compile-time. Some VMs already do that to some extent in order e.g. to better inline calls for the generic argument. Still, those optimisations are in their infancy, but the situation improves with every year. "Don't get me wrong. I am quite happy with this making my skills very rare and expensive, giving me both job security and decent compensation." Eh? C++ skills are not any more expensive than decent Java/C#/Python/(put whatever mainstream language here) skills. Who told you that? This is supply-demand. There is lower supply of C++ coders, so some may think the prices should be higher, but in fact it is compensated by lower demand. C++ is also still being taught at schools, so those skills are not that rare as, say, Haskell, Erlang or Go.
- pandaman 13y agoHow do you figure out the types at run time with zero overhead? I guess we have different concept of "zero". As for the price of my skills - my paycheck told me that. And sure, it could be low demand (there are vacancies in my field, that had been open for years, but I don't really know what kind of demand there is for Python, could be decades for all I care). I am just happy for my compensation and if others have more expensive skills - I am happy for them too :)
- pkolaczk 13y agoNothing is truly zero overhead. C++ templates are neither, because they create some overhead in code size which is obviously non-free (both space-wise and time-wise). Zero-overhead for me = optimized to the point that noone can notice. There is no problem for a VM to generate 10 versions of a tight loop, every one optimised for particular type, with a switch for the type right before entering the loop, or the whole method, or even a whole call-tree.
- pandaman 13y agoWe also mean different things by overhead. For me (and the C++ committee) it means something that is done in addition. So for me templates create zero overhead as the do not produce more code than the same, non-template code. In practice, templates produce less code as there is a higher chance to fold common code from the instantiations of the same template than from many handwritten functions.