@gentoobro
Sure, but I'm not sure I would call Rust more complicated than other languages (with the exception of the borrow checker). C++ can have a lot of fuckery when you use things like virtual methods.
@gentoobro Yeah, when programming it's hard to tell precisely how complex is everything going to be
plenty of languages have generics but compile faster than C++
@matrix The devil's in the details. Generics tend to be complicated for compilers because they can cause a combinatorial explosion of concrete implementations. Some languages and compilers handle this reasonably. Others are C++.
My understanding of the problem is something like this: PCH aside, C++ has to recompile the entire template system for every translation unit (source file). The templates have to be completely in the headers due to some petty retarded detail of how they work. Then the linker has to throw away all the duplicate template function implementations. C++ is a language with no zen.
@gentoobro Oh, if that's why then no wonder. I would guess that it's probably some technical debt from being a C superset
@matrix As I understand it, there's some petty detail in the spec that forces all the template functions to have to be in headers like static functions. Some tiny oversight like how in C two identical anonymous structs are considered different types but they're the same if you typedef them.
@mikerotch @matrix Thanks for the explanation of the details.
The question now becomes why they don't cache all the necessary information LTO style and automatically instantiate the required argument combinations at link time.
@mikerotch @matrix PCH, in my personal experience, tends to be a glitchy mess. Maybe that's just build systems and not PCH itself.
But I'm not talking about PCH. I'm talking about being able to put template function definitions in a normal source file, a separate translation unit, and then having the linker figure out what concrete versions to instantiate and then compile. This is roughly how Link Time Optimization works. The compiler keeps some form of intermediate code around for every TU and then runs a final compile and optimization pass over the whole project, inlining functions from other TU's as it sees fit. I see no reason that a C++ compiler couldn't automatically do this with templates, though there may indeed be a legitimate one.
competence and manpower are generally decreasing as demographics are deteriorating.
It's getting pretty bad...
Users of a template should be able to figure out its memory layout with just the class definitions and function declarations, no different than typical use of classes. The template function definitions, which are largely what bloats the headers, aren't truly needed until final linking of the executable or library. The compiler should be able to keep a list of which instances of which templates are needed in each TU then have the linker compile the necessary versions using cached IM code like LTO does. And all this completely without build system interaction, since it's the linker provoking the final instantiation and compilation. Function inlining would be no different than with non-template functions.
@mikerotch @matrix LTO is optional in my build system since it takes several seconds on every build.
I make extensive use of static functions, often with the same names in many TU's, so a unity build isn't directly feasible for me even for releases. I could probably automate the inclusion of some macros between each source file though, now that I think about it. I'll have to get my C parser working completely before that.
All of my static libraries are compiled as source along with the project for this exact reason. I've read that at least on GCC you can make .a's that keep the LTO information, but it's not risen up my priority list enough to test.
or_you_have_to_reinvent_them_yourself_poorly
Kind of. One::of::the::things::I::hate::about::C++::is::the::constant::use::of::"::". Sure, you can use "using namespace foo;", but then you're just back where you started. To me, unnecessary visual bloat is a dire sin in source code.
@mikerotch @matrix I usually put "using std;" in all my C++ files back before I found the true faith. std gets used constantly and frankly anything else is less important and can get out of its way.
@mikerotch @matrix Now you get into boilerplate. You essentially have to re-declare your types and functions all over the place. There's tradeoffs to everything. C++ takes one direction and I take the polar opposite.
Having my build system slap "#define appendCmds riggedMeshManager_c__appendCmds" and "#undef appendCmds" around each source file with static functions during a unity build is easy and, more importantly, completely transparent to the code. I'm already undermining malloc et. al. with globally included macros. (Another reason for compiling in the static libs by source.)
@mikerotch @matrix I'm planning to compile without libc. I need to completely remove all standard memory allocation by all code in the entire SO. Dunno if that's practical in C++; it's been quite a while since I tried any tricky.
@matrix Complexity is not always obvious. Generics tend to be complicated. C++ compilers are slow mainly because of templates.