namespace cpp {}

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:module

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.


kennen:module [2020-07-29 17:32] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +====== Module ======
 +
 +===== Abschied vom Präprozessor? =====
 +
 +Programme bestehen aus mehreren [[translation_units]], abgesehen von Ausnahmen:
 +
 +<code cpp>
 +#include <iostream>
 +int main()
 +{
 +    std::cout << "Hallo, Welt\n";
 +}
 +</code>
 +Das Einbinden anderer Quellen per ''%%#include%%'' verlangsamt den Übersetzungsprozess. Umfangreiche Header müssen immer wieder mit übersetzt werden. Manche Compiler behelfen sich mit Vorübersetzung (precompiled headers). Reihenfolge- und zyklische Abhängigkeiten (''%%#ifdef%%''und ''%%#pragma once%%''), Verletzungen der „one definition rule“, ungenügende Abschirmung von Implementierungsdetails (Pimpl-Idiom, ''%%namespace xy::detail%%'') und vor unbeabsichtigten Wirkungen von Makros (''%%__Uglified_Names%%'' in Bibliotheken) sind negative Folgen dieser Technik. //Module// ändern ab C++20 die Organisation von Quelltexten, den Übersetzungsprozess und die Arbeit von Werkzeugen (Build-Systeme, Entwicklungsumgebungen) tiefgreifend. Der Umstellungsprozess wird aber Jahre dauern.
 +
 +===== Module importieren =====
 +
 +Übersetzungseinheiten können Module importieren und nutzen:
 +
 +<code cpp>
 +import hello;
 +int main()
 +{
 +    greeting();
 +}
 +</code>
 +Importierbar sind (übergangsweise?) auch C++-Header wie ''%%<iostream>%%''. Die Standardbibliothek wurde in C++20 noch nicht modularisiert. Modulnamen, die mit ''%%std%%'', evtl. gefolgt von Ziffern, beginnen, sind für die Standardbibliothek reserviert. Modulnamen können durch Punkte unterteilt werden: ''%%std.core%%'' und ''%%std.core.algorithm%%'' wären trotz gleicher Namensteile voneinander unabhängige Module.
 +
 +===== Schnittstelle =====
 +
 +Ein Modul besteht aus genau einer Modul-Schnittstellen-Datei und null bis vielen Implementierungsdateien. Kennzeichen einer Modulschnittstelle ist die Anweisung ''%%export module modulname;%%''
 +
 +<code cpp>
 +export module hello;
 +export void greeting();
 +</code>
 +In der Schnittstelle werden alle zum Modul gehörenden und vom Modul exportierbaren Namen aufgeführt. Das Schlüsselwort ''%%export%%'' steht vor einzelnen Deklarationen, vor Klassen, Funktionen, Schablonen, Namensräumen, oder als Block ''%%export {...}%%''. Makros werden nicht exportiert.
 +
 +===== Implementierung =====
 +
 +Funktionen werden in der Modulschnittstelle oder anderen zum Modul gehörenden Dateien definiert:
 +
 +<code cpp>
 +module hello;
 +import <iostream>;
 +void greeting() { std::cout < "Hello, world\n"; }
 +</code>
 +Die Zugehörigkeit zu einem Modul wird durch ''%%module modulname;%%'' festgelegt. Dabei kann auf alle in der Schnittstelle aufgeführten Namen zurückgegriffen werden. Modulname und ''%%import%%''-Anweisungen stehen vor allem anderen Deklarationen eines Moduls.
 +
 +===== Reexportieren =====
 +
 +<code cpp>
 +export module noodles;
 +export import spaghetti;
 +...
 +</code>
 +erlaubt, die Schnittstellen anderer Module mit zu exportieren.
 +
 +===== Partitionen =====
 +
 +<code cpp>
 +export module geometry:vector;
 +...
 +</code>
 +Modulpartitionen, erkennbar am Doppelpunkt im Namen, können nur von dem übergeordneten Modul importiert und auch reexportiert werden:
 +
 +<code cpp>
 +export module geometry;
 +export import :vector;
 +</code>
 +Auch Modulpartitionen können neben der Schnittstelle weitere Implementierungsdateien besitzen.
 +
 +===== Globales und privates Fragment =====
 +Eine Modul(schnittstellen)datei hat zwingend folgende Struktur (Teile in Eckigen Klammern können wegfallen):
 +<code cpp>
 +[                           // nur Kommentare
 +module;                     // globales Modulfragment
 +...    ]                    // nur Präprozessoranweisungen
 +[export] modul modulname;   // Modulpräambel
 +[export][import andere;   // Importbereich
 +...                         // Modulbereich
 +[module :private;           // privates Modulefragment 
 +...    ]
 +</code>
 +Eine Modulschnittstelle mit privatem Modulbereich darf keine weiteren Implementierungsdateien haben.
 +===== Modul-Bindung =====
 +
 +Neben lokaler und externer Bindung führt das Modulsystem eine weitere Bindungsart ein. Innerhalb von Modulschnittstellen definierte Variablen sind innerhalb aller Übersetzungseinheiten des Moduls nutzbar. Mit anderen externen Variablen kollidieren sie nicht, wenn sie nicht exportiert werden, wie dieses Beispiel mit mehreren Modulpartitionen zeigt:
 +
 +<code cpp>
 +export module walk:position;
 +int x = 0;
 +</code>
 +<code cpp>
 +export module walk:steps;
 +import :position;
 +
 +export void forward() { ++x; }
 +export void back() { --x; }
 +</code>
 +<code cpp>
 +export module walk;
 +export import :steps;
 +import :position;
 +
 +export auto get_position() { return x; }
 +</code>
 +<code cpp>
 +// does not collide with x in module walk:
 +int x = 7;
 +</code>
 +<code cpp>
 +import walk;
 +import std.core; // Visual C++ 2019: instead of 
 +// import <iostream>; 
 +
 +int main()
 +{
 +    forward();
 +    forward();
 +    back();
 +    std::cout << get_position() << " steps gone\n";
 +
 +    extern int x;
 +    std::cout << x << " is another, unaffected global variable\n";
 +}
 +</code>
 +
 +===== Übersetzungsprozess =====
 +
 +Modulschnittstellen als auch Implementierungsdateien sind einzelne Übersetzungseinheiten, die beim Übersetzen zu Ohjektdateien (''%%*.o%%'', ''%%*.obj%%'') werden. Bevor Module importiert werden können, müssen die Modulschnittstellen bekannt sein. Dazu müssen die Schnittstellen zuerst, in der Reihenfolge ihrer Abhängigkeiten, verarbeitet werden. Zyklische Abhängigkeiten sind nicht erlaubt. Die Art, wie Compiler die Informationen dieser Schnittstellen aufbereiten, vorhalten und wiederfinden, z.B. als binary module interface (''%%*.bmi%%'', ''%%*.ifc%%''), ist implementierungsabhängig. Hier kommt noch viel Arbeit auf die Hersteller von Buildsystemen zu.
 +
 +^Übersetzungseinheit  ^                           ^Dateiendung((Dateiendungen sind System- bzw. Compiler-implementierungsabhängig.))^erzeugt                                     ^
 +|Modul-Schnittstelle  |''%%export module name;%%''|''%%*.cppm%%'' / ''%%*.ixx%%''                                                   |''%%.o%%'' und ''%%*.bmi%%'' / ''%%*.ifc%%''|
 +|Importierbare Header |''%%import <header>;%%''                                                                                                                              |
 +|                     |''%%import “header”;%%''   |''%%*.hpp%%'' / ''%%*.h%%''                                                      |''%%.o%%'' und ''%%*.bmi%%'' / ''%%*.ifc%%''|
 +|Modul-Implementierung|''%%module name;%%''       |''%%*.cpp%%''                                                                    |''%%.o%%''                                  |
 +|Konsument            |''%%import name;%%''       |''%%*.cpp%%''                                                                    |''%%.o%%''                                  |
 +
 +<code>
 +*.ixx -> Prepocess/Compile -> *.obj  Libraries           
 +            v                  \    / 
 +           *.ifc                Link -> program
 +            v                  /
 +*.cpp -> Compile -> *.obj
 +</code>
  
kennen/module.txt · Zuletzt geändert: 2020-07-29 17:32 von 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki