Compile-time function execution, constexpr
Verfasst: 22.04.2021, 20:36
Hallo zusammen,
ich habe mal eine Frage zu constexpr und dessen Nutzung zum/zur Compile-time programming/function execution: Mir fällt es momentan schwer, wirklich praktische Beispiele zu finden, wo der Einsatz über Showcases oder den Missbrauch des Compilers als Taschenrechner hinausgeht. Was ich damit meine:
Beispiel 1: Selbst wenn ich noch so komplexe mathematische Ausdrücke zur Compile-Zeit berechnen kann, müssen irgendwo ganz am Anfang konstante Werte rein. Das könnte ich auch außerhalb der Programmiersprache ausrechnen und einfach das Resultat in den Code schreiben. Dann habe ich einmal Aufwand außerhalb der Programmierwelt, die gleiche Laufzeit und jedesmal verringerte Compile-Zeit.
Selbst wenn es wegen Bedingungen und ähnlichem händisch zu aufwendig wird, würde ich das Programm, das mir die Berechnungen durchführt (der "Taschenrechner"), auslagern. Dann kann ich aber auch gleich wieder zur Runtime rechnen, da es sich nicht auf das Hauptprojekt auswirkt und die Compile-Zeit-Berechnung langsamer ist, siehe nächstes Beispiel.
Beispiel 2: Es gibt ja mittlerweile ganze Raytracer auf GitHub, die eine statische Szene zu Compile-Zeit rendern. Jetzt könnte ich mir vorstellen, die verschiedenen Szenen, die ich generieren möchte (oder andere Resourcen, wenn man vom Raytracer weggeht), alle direkt in Codeform zu speichern und vor dem Kompilieren einfach den richtigen Header einbinden. Das wäre sinnvoll, wenn nicht der Compile-Time Raytracer wesentlich langsamer wäre, als der Runtime-Raytracer. In einem C++17-Projekt bei GitHub wird hier der Faktor 6000 genannt. D.h. der einzige Vorteil an der Stelle ist, dass ich die exakt gleiche Szene mehrfach rendern kann und ab dem sechstausendersten Mal dann womöglich schneller bin, als die Runtime-Variante.
Beispiel 3: Ich habe in einem vergangenen Projekt über rekursive Templates Schleifen abgebildet, um alle möglichen bekannten Funktionssignaturen, die ich für ein sehr generellen std::function-Wrapper haben wollte, abzubilden. Das war hilfreich, hatte aber nicht den Sinn, die Laufzeit zu verbessern, sondern war lediglich eine Krücke, um mit std::function und sauberen Template-Parametern zu arbeiten. Das alles hätte ich mir mit void-Pointern ersparen können.
Ich hoffe, es ist klar geworden, worauf ich hinaus will.
Beste Grüße
Edit: Kurzer Nachtrag: Ein paar Dinge, die mir einfallen, sind Komfortfunktionen wie constexpr-Strings. Aber danach wird es dünn, mit meiner Vorstellungskraft.
ich habe mal eine Frage zu constexpr und dessen Nutzung zum/zur Compile-time programming/function execution: Mir fällt es momentan schwer, wirklich praktische Beispiele zu finden, wo der Einsatz über Showcases oder den Missbrauch des Compilers als Taschenrechner hinausgeht. Was ich damit meine:
Beispiel 1: Selbst wenn ich noch so komplexe mathematische Ausdrücke zur Compile-Zeit berechnen kann, müssen irgendwo ganz am Anfang konstante Werte rein. Das könnte ich auch außerhalb der Programmiersprache ausrechnen und einfach das Resultat in den Code schreiben. Dann habe ich einmal Aufwand außerhalb der Programmierwelt, die gleiche Laufzeit und jedesmal verringerte Compile-Zeit.
Selbst wenn es wegen Bedingungen und ähnlichem händisch zu aufwendig wird, würde ich das Programm, das mir die Berechnungen durchführt (der "Taschenrechner"), auslagern. Dann kann ich aber auch gleich wieder zur Runtime rechnen, da es sich nicht auf das Hauptprojekt auswirkt und die Compile-Zeit-Berechnung langsamer ist, siehe nächstes Beispiel.
Beispiel 2: Es gibt ja mittlerweile ganze Raytracer auf GitHub, die eine statische Szene zu Compile-Zeit rendern. Jetzt könnte ich mir vorstellen, die verschiedenen Szenen, die ich generieren möchte (oder andere Resourcen, wenn man vom Raytracer weggeht), alle direkt in Codeform zu speichern und vor dem Kompilieren einfach den richtigen Header einbinden. Das wäre sinnvoll, wenn nicht der Compile-Time Raytracer wesentlich langsamer wäre, als der Runtime-Raytracer. In einem C++17-Projekt bei GitHub wird hier der Faktor 6000 genannt. D.h. der einzige Vorteil an der Stelle ist, dass ich die exakt gleiche Szene mehrfach rendern kann und ab dem sechstausendersten Mal dann womöglich schneller bin, als die Runtime-Variante.
Beispiel 3: Ich habe in einem vergangenen Projekt über rekursive Templates Schleifen abgebildet, um alle möglichen bekannten Funktionssignaturen, die ich für ein sehr generellen std::function-Wrapper haben wollte, abzubilden. Das war hilfreich, hatte aber nicht den Sinn, die Laufzeit zu verbessern, sondern war lediglich eine Krücke, um mit std::function und sauberen Template-Parametern zu arbeiten. Das alles hätte ich mir mit void-Pointern ersparen können.
Ich hoffe, es ist klar geworden, worauf ich hinaus will.
Beste Grüße
Edit: Kurzer Nachtrag: Ein paar Dinge, die mir einfallen, sind Komfortfunktionen wie constexpr-Strings. Aber danach wird es dünn, mit meiner Vorstellungskraft.