We present programming techniques to illustrate the facilities and principles of C++ generic programming using concepts. Concepts are C++'s way to express constraints on generic code. As an initial example, we provide a simple type system that eliminates narrowing conversions and provides range checking without unnecessary notational or run-time overheads. Concepts are used throughout to provide user-defined extensions to the type system. The aim is to show their utility and the fundamental ideas behind them, rather than to provide a detailed or complete explanation of C++'s language support for generic programming or the extensive support provided by the standard library. Generic programming is an integral part of C++, rather than an isolated sub-language. In particular, key facilities support general programming as well as generic programming (e.g., uniform notation for types, lambdas, variadic templates, and C++26 static reflection). Finally, we give design rationales and origins for key parts of the concept design, including use patterns, the relationship to Object-Oriented Programming, value arguments, notation, concept type-matching, and definition checking.
Dieses Paper zeigt Programmiertechniken zur Veranschaulichung von C++-Einrichtungen und Prinzipien der generischen Programmierung unter Verwendung von Konzepten (Concepts). Konzepte sind die Methode von C++, um Einschränkungen in generischem Code auszudrücken. Als anfängliches Beispiel wird ein einfaches Typsystem bereitgestellt, das Verengungskonvertierungen eliminiert und Bereichsprüfungen ohne unnötige Notation oder Laufzeitaufwand ermöglicht. Konzepte werden umfassend zur Bereitstellung von benutzerdefinierten Typsystemerweiterungen verwendet. Das Paper zielt darauf ab, die Praktikabilität von Konzepten und die zugrunde liegenden Grundideen zu demonstrieren, anstatt eine detaillierte oder umfassende Erklärung der Sprachunterstützung oder der umfangreichen Standardbibliotheksunterstützung für generische Programmierung zu bieten. Generische Programmierung ist ein integraler Bestandteil von C++, keine isolierte Untersprache. Abschließend werden die Designphilosophie und der Ursprung der Schlüsselaspekte des Konzeptdesigns dargelegt, einschließlich Verwendungsmuster, Beziehung zur objektorientierten Programmierung, Wertparameter, symbolische Darstellung, Konzepttypabgleich und Definitionsprüfung.
Herausforderungen der generischen Programmierung: Die traditionelle C++-Programmierung mit Vorlagen mangelt es an expliziten Schnittstellenspezifikationen, was zu undurchsichtigen Kompilierungsfehlermeldungen führt, die sowohl Programmierer als auch Compiler schwer verstehen und verwenden können.
Typsicherheitsprobleme: C++ erbt die impliziten Typkonvertierungsregeln der Sprache C, insbesondere Verengungskonvertierungen zwischen arithmetischen Typen (z. B. Konvertierungen von großen zu kleinen Ganzzahlen können Informationen verlieren), was eine wichtige Quelle für Fehler und Sicherheitsprobleme darstellt.
Fehlende Bereichsprüfung: Die traditionelle Verwendung von Zeigern und Arrays führt leicht zu Sicherheitsproblemen wie Pufferüberläufen und mangelt es an wirksamen Bereichsprüfungsmechanismen.
Das Paper folgt dem von Alex Stepanov vorgeschlagenen Ziel der generischen Programmierung: „Das universellste, effizienteste und flexibelste Konzept darstellen" und erfüllt die folgenden Designanforderungen:
Universalität: Muss in der Lage sein, mehr auszudrücken, als man sich vorstellen kann
Kompromisslose Effizienz: Generischer Code sollte keinen Laufzeitaufwand im Vergleich zu äquivalentem Low-Level-Code verursachen
Statisch typsichere Schnittstelle: Das Typsystem muss flexibel genug sein, um Kompilierungsprüfungen zu ermöglichen, die nicht von Laufzeitwerten abhängen
Konzeptbasierte Typsicherheitsprogrammiertechniken: Zeigt, wie man Konzepte nutzt, um Verengungskonvertierungen zu eliminieren und Bereichsprüfungen bereitzustellen, während Null-Laufzeitaufwand beibehalten wird.
Konstruktion praktischer Typsystemerweiterungen:
Implementierung des Number<T>-Typs zur Eliminierung gefährlicher Verengungskonvertierungen
Entwurf eines sicheren Span-Typs mit Bereichsprüfung für Array-Zugriff
Demonstration der Konzeptanwendung im Algorithmusdesign
Bereitstellung tiefgreifender Designphilosophie für Konzepte: Detaillierte Erläuterung von Designentscheidungen für Konzepte als Kompilierungszeitfunktionen, Beziehung zur objektorientierten Programmierung, Symboldarstellungsauswahl und andere kritische Designüberlegungen.
Demonstration der Einheit generischer Programmierung: Nachweis, dass generische Programmierung ein integraler Bestandteil von C++ ist, keine isolierte Untersprache, und sich nahtlos mit anderen Sprachfeatures (wie Lambda, variadische Templates, statische Reflexion) integriert.
template<Num U, Num T>
constexpr bool will_narrow(U u) {
if constexpr (!Can_narrow_to<T, U>)
return false;
// Laufzeitprüfung nur bei möglicher Verengung
T t = u;
return (t != u);
}
Durch Kompilierungszeitprüfungen und bedingte Kompilierung wird Null-Laufzeitaufwand erreicht:
template<Num U, Num T>
constexpr bool will_narrow(U u) {
if constexpr (!Can_narrow_to<T, U>)
return false; // zur Kompilierungszeit bestimmt, kein Laufzeitaufwand
// Laufzeitprüfung nur bei Bedarf
}
Das Paper weist darauf hin, dass viele Constraint-Systeme auf Funktionssammlungen (ähnlich wie Klassendefinitionen) angewiesen sind, während C++-Konzepte einen funktionalen Ansatz verwenden und größere Flexibilität bieten.
Steile Lernkurve: Die Syntax und Verwendungsmuster von Konzepten können für Anfänger relativ komplex sein.
Auswirkungen auf Kompilierungszeit: Umfangreiche Kompilierungszeitprüfungen können die Kompilierungszeit erhöhen, was im Paper nicht ausreichend diskutiert wird.
Herausforderungen der Rückwärtskompatibilität: Obwohl die Kompatibilität beibehalten wird, kann die gemischte Verwendung von altem und neuem Code zu Verwirrung führen.
Qualität von Fehlermeldungen: Obwohl Konzepte Fehlermeldungen verbessern, können Fehlermeldungen für komplexe Konzepte immer noch schwer zu verstehen sein.
Das Paper enthält umfangreiche Referenzen, die verschiedene Aspekte von der C++-Sprachgestaltung bis zur Theorie der generischen Programmierung abdecken, hauptsächlich einschließlich:
Bahnbrechende Arbeiten von Alex Stepanov zu STL und generischer Programmierung
Technische Berichte und Vorschläge des C++-Standardkomitees
Historische Dokumente des Autors zur C++-Gestaltung und -Entwicklung
Verwandte Forschung zur Programmiersprachentheorie
Zusammenfassung: Dies ist ein Paper mit wichtigem theoretischem und praktischem Wert, verfasst vom Schöpfer der C++-Sprache selbst, das umfassend die Anwendung von Konzepten in der C++-Programmierung mit Vorlagen demonstriert. Das Paper bietet nicht nur praktische Programmiertechniken, sondern erläutert auch tiefgreifend die Designphilosophie und hat wichtigen Referenzwert für C++-Programmierer und Forscher im Bereich Programmiersprachen.