Zoals @
Snoitkever is dit voor C++ helaas geen oplosbaar probleem...
Het model van C++ is dat elke source file die je compileert als onafhankelijke 'translation unit' wordt behandeld, en daarbij
al zijn afhankelijkheden mee trekt, dus alle header files die (recursief) #geinclude worden, etc. Al die code wordt voor elke translation unit opnieuw gecompileerd. Gooi je ook nog templates in de mix, dan genereert de compiler code voor elke template instantiate die je gebruikt, en ook dat moet allemaal weer gecompileerd worden. Schrijf je modern C++ en maak je gebruik van technieken als CRTP voor compile-time polymorphisme, dan is al snel bijna alles wat je schrijft automatisch een template. En dan zijn er nog trucs als SFINAE waarbij je template 'fouten' gebruikt om compile-time functies te restricten op eigenschappen van bijvoorbeeld de types die je in gooit. Wat de compiler doet als je zo'n functie aanroept is de template voor *alle* mogelijke versies van je functie om 'uit te proberen' welke er 'past'. Libraries als Boost gebruiken dit soort template metaprogramming soms met tientallen of honderden mogelijke overloads. Oh en aan het eind van de rit moet alles ook nog gelinked worden, wat ook absurd lang kan duren.
Anyway, om een lang verhaal kort te maken, zo lang je dat allemaal niet gebruikt dan valt het redelijk mee, maar het probleem is dat veel van deze features super handig zijn en allerhande voordelen hebben (compile time tijd inleveren voor minder run-time overhead, compactere code die makkelijker te onderhouden is, etc). En sinds C++11 en leunt ook de standard template library steeds meer op dit soort technieken.
Dat is waarom game programmers een hekel hebben aan 'modern C++' en liever 'orthodox C++' (ook wel 'C with classes') schrijven (geen enkel gebruik maken van alle moderne features), en vaak 'unity builds' gebruiken (in plaats van verschillende source files 1-voor-1 compileren, de code van je hele programma in 1 file #includen zodat je hem als 1 translation unit kan compileren). Dat kan allemaal maar dan mis je een hoop voordelen van de taal, en je introduceert weer allerhande andere problemen kwa maintenance en deployment.
Edit:
Er wordt overigens wel gewerkt aan 'workarounds' om dit soort problemen iets te beperken, bijvoorbeeld support voor 'modules' in C++20. Dan is het idee dat je code kunt schrijven die niet zijn afhankelijkheden niet door middel van #includes vastlegt, maar in termen van de interfaces van modules die de code wil aanroepen. De compiler hoeft dan alleen maar te controleren dat er ergens in de build een module is die voldoet, en hoeft dan niet alle headers van die module te gaan inladen en compileren. Dit lijkt veel meer op hoe talen als Java etc. werken. Maar heel veel dingen die je via templates kunt doen kun je niet in module interfaces gebruiken als ik het goed begrijp (heb er nog nooit serieus naar gekeken omdat er tot op de dag van vandaag nog maar beperkte support is voor C++20 en de voorstellen voor modules volgens mij pas een paar maanden geleden definitief geaccepteerd zijn).
[Reactie gewijzigd door johnbetonschaar op 29 juli 2024 08:08]