C++ Modules

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2348
Registriert: 04.08.2004, 20:06
Kontaktdaten:

C++ Modules

Beitrag von Jonathan »

Hey,

hat schon jemand Erfahrung mit C++ Modulen gesammelnt? Es scheint ja zumindest ansatzweise in VC 2017 implementiert zu sein, ich habe vor längerem mal ein Video dazu gesehen, und frage mich, inwieweit das schon benutzbar ist.

https://blogs.msdn.microsoft.com/vcblog ... udio-2017/
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Habe es zur Zeit des Blog-Posts genutzt. Benutzbar sind sie mit der Einschränkung, dass du exakt in der richtigen Reihenfolge kompilieren musst (indem die Module in alphabetisch sortierten Namen vorliegen und das Kompilieren auf einen CPU-Kern beschränkt ist). Das war mir ein Bisschen viel Aufwand, und dann habe ich sie zur Seite gelegt.

Keine Ahnung, wie weit sie heute sind. Ich möchte sie auch unbedingt in der nächsten Zeit wieder testen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2348
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: C++ Modules

Beitrag von Jonathan »

1.5 Jahre später. Ich überlege fast, sie mir nochmal anzusehen. Hat in der Zwischenzeit jemand damit Erfahrung gesammelt?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Ich nicht. Bin vor allem daran interessiert, ob MSBuild nun endlich die Build-Reihenfolge auf die Kette kriegt … sonst lohnt sich das Ausprobieren gar nicht.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Ein Jahr nach meinem letzten Experiment. Visual Studio 2019 16.5.0 Preview 1.0 erkennt noch immer nicht die korrekte Reihenfolge der Abhängigkeiten; also noch immer unbrauchbar.

Ein halbwegs praktisch einsetzbarer Weg ist, die .vcxproj-Datei von Hand zu ändern, so dass alle Module in der korrekten Reihenfolge eingetragen sind. Dann muss allerdings auch parallele Kompilierung abgeschaltet werden. Bei dem Vergleich 12 Threads mit Headern gegen einen Thread mit Modules gewinnt nunmal die Header-Variante.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2348
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: C++ Modules

Beitrag von Jonathan »

Vielen Dank für das Update, auch wenn es eher deprimierend ausfällt. Ugh...
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Besserung ist absehbar: https://devblogs.microsoft.com/cppblog/ ... sion-16-7/

Ich muss noch testen, ob diese Information nun endlich in MSBuild verwertet wird.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: C++ Modules

Beitrag von NytroX »

Habe die Hoffnung relativ aufgegeben. Vielleicht in 10 Jahren.

Also ich mache alle meine neuen Abhängigkeiten als Header-Only, dann habe ich quasi Module.
D.h. alle Funktionen/Variablen werden inline, static inline, constexpr und/oder sind templates.
Dann einfach #include und fertig.
Ich habe nur noch eine main.cpp, alles andere sind *.h

Module dauern einfach zu lange... macht keinen Sinn zu warten.

Ansonsten auch einfach D benutzen, die haben seit Jahren ordentliche Module und generieren den Code ja letztlich auch über LLVM, ist also auch schnell - und da kann man auch die Abhängigkeiten zwischen Klassen definieren, anstatt zwischen Files - das wird nie was ordentliches werden in C++.
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

In meinen Experimenten waren Module ganz brauchbar – eben so lange die Abhängigkeiten alphabetisch sortiert sind.

Header-only ist mir viel zu langsam, weil die Abhängigkeiten viel zu schnell wachsen (A #includet B, das wiederum #includet C und D, …). Ich habe ja schonmal geschätzt, dass ohne Header die Kompilierzeit großer Projekte ungefähr auf ein Hundertstel(!) sinken dürfte: viewtopic.php?f=9&t=1929&p=62362#p62362

Um das zu stützen, habe ich letztens noch keine wirklichen Analysen finden können. Nur einen Kommentar des LLVM-Teams, dass ihnen kein einziges Projekt bekannt wäre, das durch Modules nicht schneller kompilieren würde.

Nachtrag: Visual Studio 16.8.0 Preview 1.0 kann die Reihenfolge noch immer nicht automatisch bestimmen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: C++ Modules

Beitrag von NytroX »

Freue mich, dass sie für dich funktioniert haben, das gibt zumindest etwas Hoffnung.
Und klar, richtige Module sind natürlich die beste Lösung.

Aber macht euch mal auf ein paar Überraschungen gefasst, was den Performance-Gewinn angeht.
Schlechtes Design einer Applikation bleibt langsam, egal ob mit Modulen oder ohne.

Leider schaut man überhaupt nicht darauf, welche Probleme FORTRAN, Java, C# oder D bei der Implementierung hatten/haben.
Ich denke der Kommentar der LLVM Entwickler ist... sagen wir mal... etwas zu blauäugig :-P
... und ein Grund, warum Module so lange dauern, und auch noch dauern werden.
Und das wissen wir doch eigentlich alle: nichts vermuten, sondern profilen!
Ich sage nur: "export import ..." => killt die Performance und alle werden es nutzen. Für andere Sprachen ein "Klassiker" :-)

Hier mal ein paar Links dazu:
https://vector-of-bool.github.io/2019/0 ... s-doa.html
https://bfgroup.github.io/cpp_tooling_s ... 441R1.html
http://www.open-std.org/jtc1/sc22/wg21/ ... 1427r0.pdf

Zu meinem Vorgehen:
Ich kompiliere bei mir natürlich auch kein Chromium, sondern nur einige hunderttausend LOC.
Und man findet nicht für alles Header-Only Libraries, also nicht für jedes Projekt einsetzbar.
when you #include a bunch of source files together then the compiler treats them as one translation unit
Nach meiner Erfahrung für kleine bis mittlere Projekte völlig ok. Für Chromium natürlich eher nicht so pralle...
Alles was größer ist, verteile ich auf mehrere .dll/.so => Problem "gelöst" :-)

Was ich aber auch gut daran finde ist das "Build-Framework", habe nämlich keins und brauche auch keins:

Code: Alles auswählen

zig c++ -O3 -std=c++20 -target x86_64-linux-musl -o app app.cpp
Das war jetzt mal nur der Linux build, generiert eine Binary, die quasi auf jeder Linux-Distro lauffähig ist (weil alle Dependencies mit reincompiliert werden).
Geschwindigkeit? für die o.g. ca. 300.000 LOC: < 3 Sekunden (inkrementell, macht alles zig für mich) und < 8 Sekunden (komplettes Projekt, aber ohne libc++ und musl).

Ist mMn auch einer der großen Vorteile von Modulen: Ich brauche dem Compiler nicht die ganzen Abhängigkeiten zu verklickern; wenns denn klappt (siehe mein letzter Link oben).
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Danke für die Links, die kannte ich noch nicht!
NytroX hat geschrieben: 16.08.2020, 14:44Zu meinem Vorgehen: […]
when you #include a bunch of source files together then the compiler treats them as one translation unit
Nach meiner Erfahrung für kleine bis mittlere Projekte völlig ok. Für Chromium natürlich eher nicht so pralle...
Alles was größer ist, verteile ich auf mehrere .dll/.so => Problem "gelöst" :-)
Meinst du, du machst Unity Builds? Aller Code in ein Modul?

Die Messung der Build-Parallelität im zweiten Link ist super. Deren Zusammenfassung im ersten Link finde ich aber völlig daneben:
Are modules fast? Spoiler alert: No. Or, more accurately: It’s subtle, but mostly no.
Gezeigt wurde doch, dass die Header-Parallelität bei 16–32 CPU-Kernen mit Modulen gleichzieht. Darunter – also auf so ziemlich jedem Entwickler-Computer – sind Module schneller fertig. Darüber – also vor allem auf Build Servern oder auf Job Distribution-Systemen – sind Header schneller kompiliert, aber bei einem Vielfachen der CPU-Zeit.

Und das kann ich gar nicht genug betonen: In den Diagrammen unten (128 Threads) dauert es zwar vier Mal so lange, bis die Module fertig sind (12 vs 3.5 s), aber die CPU-Auslastung ist ungefähr hundert Mal so hoch! Da wir hier über Parallelität sprechen, die auf Einzelrechnern eher selten ist, würde ich das eher für Module auslegen und behaupten, dass ein Build Server oder ein Job-System nun mindestens zehn Mal so viele Versionen parallel verarbeiten kann wie vorher?!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: C++ Modules

Beitrag von NytroX »

Ja, könnte man Unity-Builds nennen, weil das ja dabei rauskommt, wenn man nur Header #included (sieht ja für den Compiler so aus, als wärs nur eine große Datei).
Wichtig ist halt wie gesagt, dass man ne ordentliche Abhängigkeitsstruktur in seinem Programm hat, "#pragma once" o.ä. verwendet und halt auch mit "inline" arbeitet und wenig Preprocessor-Quatsch benutzt. Aber ich denke das ist ja logisch ;-)

Zu deinem letzten Abschnitt: ja, gebe ich dir vollkommen recht.
Ich denke Multithreading ist generell noch nicht so in den Compilern angekommen, sondern eher noch eine Baustelle. Hat aber ja nix mit der Sprache an sich zu tun. Man merkt halt, dass vor allem C++ Compiler mehrere Jahrzehnte auf dem Buckel haben.
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Ja; ich stimme übrigens auch den Artikeln in vielem zu. Dass Modules unausgereift sind und monströse Komplexität mit sich bringen, steht kaum zur Debatte.

Ich würde mich sehr freuen, wenn hier mehr in die IDE verlagert würde. Jede moderne IDE parst sowieso das ganze Projekt um daraus Browsing-Informationen zu erzeugen. Da kann man im Hintergrund den AST speichern und die Kompilierzeit locker halbieren. Natürlich wird dadurch kein Buildserver schneller, aber der Entwickler würde viel schneller Feedback für den Code bekommen, an dem er gerade arbeitet.

Wo du Präprozessor-Quatsch erwähnst: Der Präprozesser ist meiner Erfahrung nach rasend schnell; viel schneller z. B. als constexpr. Ich kann auch hier nur Profiling empfehlen. Meine Erfahrung ist bspw., bei Visual C++ ist die Definition von 20 leeren Namespaces in einem Header zeitintensiver als 2000 Zeilen dichter Präprozessorquatsch und Funktionsdeklarationen direkt darüber.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Visual Studio hat’s vollbracht: https://devblogs.microsoft.com/cppblog/ ... sion-16-8/
The project build will automatically scan the Modules and Header Unit files (according to their Compile As setting), for other Module and Header Units dependencies in the same project, and build them in the correct dependency order.
Und mit diesem, von mir seit fünf Jahren entgegengefieberten, Feature kommen sie natürlich drei Minuten nachdem ich im Bett sein müsste.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Ich komme nicht klar.

Sinnhaftes Beispiel (tatsächlicher Code deutlich komplexer). Ich deklariere ein Modul:

Code: Alles auswählen

export module Test;

#include <cstring>;

export size_t strlen_wrapper(char const * string) {
    return std::strlen(string);
}
Ich nutze es in einer anderen Übersetzungseinheit:

Code: Alles auswählen

#include <cstring>
import Test;

auto old = std::strlen("foo");
auto nuw = strlen_wrapper("foo");
… und nun kompiliert nichts mehr weil

error C2668: 'std::strlen': ambiguous call to overloaded function

Okaaaay. Also vertausche ich das #include mit dem import und

error: 'std::strlen' has already been defined

Das Problem scheint zu sein, dass ich zwei Mal #include <cstring> habe – einmal im Modul und einmal in der Übersetzungseinheit, die das Modul benutzt. Dadurch ist die Funktion doppelt deklariert(!).

Ich bin baff weil ich dachte, aus einem Modul würden nur Symbole exportiert werden, die export deklariert sind?! Der Compiler schlägt mir die Definition doppelt als Kandidat vor, und sagt nicht, worin sie sich die beiden Versionen unterscheiden. Ich kann das auch static, inline oder als template deklarieren – es bleibt doppelt definiert.

Schiebe ich das export module Test hinter das #include, kompiliert nichts mehr, weil die Module Declaration am Anfang der Datei stehen muss.

Ich bin perplex, denn letztes Jahr ging all das noch.

Entweder ist Visual Studio hier Schrott, oder Modules sind im finalen Standard nochmal deutlich schwieriger nutzbar geworden.

HOLY SHIT ich hab’s

Aus einem Module wird alles exportiert, was static oder inline ist. Ein anonymes Namespace (namespace { size_t strlen(); }) ist das einzige, was den Export verhindert. static exportiert, inline exportiert, beide lösen doppelt definierte Symbole aus. Nur namespace nicht.

Das kann doch nicht richtig sein?!

Nachtrag 2: Mit anonymen Namespaces statt static klappt die Übersetzung, aber der Linker findet nicht eine einzige Funktion aus den Modulen. Ich geh pennen
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: C++ Modules

Beitrag von xq »

Das kann doch nicht richtig sein?!
Doch, das ist komplett bekloppt. Die haben versucht, Module so nah an Headern zu halten wie möglich. Und damit exportieren Header natürlich alle static und inline-Funktionen *facepalm*
Ich hatte mit den TS mal durchgelesen und mir einfach die Hand auf die Stirn geklatscht. Man hätte so viel besser machen können. Und was is? Jetzt haben wir alle Probleme aus Headern UND die Probleme mit Modulen. GEIL.
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Jein. Ich bin endlich auf das gekommen, was weder die Microsoft Docs noch die meisten Tutorials erwähnen:

    module; // Muss am Anfang der Datei stehen

    // Alles, was hier steht – also auch Inhalt von #includes – wird nicht exportiert

    export module Test; // Jetzt wird’s ernst

    // Ab hier landet alles im Module Purview
    // Das kann also mit anderen Dateien kollidieren, auch wenn es nicht explizit export markiert ist


Module mit einem nicht-exportierten Teil zu beginnen und mit einem exportierten Teil zu beenden ist ja an sich nicht schlecht (eben auch wegen #includes). ABER DAS MUSS MAN ERSTMAL WISSEN

Nachtrag: Zumindest vector of bool hat es: https://vector-of-bool.github.io/2019/1 ... e-fragment
Congratulations on making it thus far!
Und nein, ES FUNKTIONIERT IMMER NOCH NICHT
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Ich komme besser klar, aber …

… Module funktionieren nicht mit __restrict. Heißt: VC++ versemmelt die Signatur und die Funktion wird nirgends gefunden.

oh no

Und #pragma darf in Modulen nicht vorkommen (haben sie wohl in der neuen Syntax vergessen).

Edit-and-Continue geht nicht, weil Modules kein /INCREMENTAL unterstützen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Okay, das ist alles ganz ganz große Scheiße und *tatsächlich* Dead on Arrival.

Vor zwei Jahren haben Microsoft ihren Modules-Vorschlag in Visual C++ umgesetzt. Ich habe ein mittelgroßes Projekt auf diesen Vorschlag portiert. Der Support des Build-Systems war quasi nicht existent, deshalb musste ich das Projekt immer *zwei Mal* kompilieren, bis es klappte.

Aber ich hatte an einem Tag alles fertiggekriegt.

Ich schrieb module Text; in meine Parser-cpp, schrieb export vor jede Funktion, die ich außen verwenden wollte, löschte den Header, ersetzte #include "Text.hpp" durch import Text; und alles funktionierte.

Heute ist die Situation anders. Bevor ihr Modules benutzen könnt, müsst ihr erstmal lernen, was ein Fragment ist und das globale und private Fragment und der Unterschied zwischen Visibility und Reachability. Und was Module Linkage und ein Module Perview ist.

Dazu kommt, dass ihr die Syntax auswendig lernen müsst. Pro Modul müsst ihr module; oder export module foo; oder module :private; oder export import :bar einsetzen. Jedes davon bringt eine eigene Syntax mit („Ab jetzt sind nur Präprozessoranweisungen erlaubt“) und die Reihenfolge ist wichtig.

Ich habe nach zwei Tagen noch immer nicht richtig kapiert, wozu man das export-Schlüsselwort nun eigentlich braucht.

Dann kommt ihr in die unangenehme Situation, dass Module keine Header #includen dürfen, die auch irgendwo im Rest des Projektes benutzt werden(!!!). Ein Modul darf also nicht <Windows.h> oder <SDL.h> einbinden, sonst sind die nur noch exklusiv für das eine Modul verfügbar und nicht für den Rest des Projekts(!!!).

Das könnt ihr teilweise umschiffen, indem ihr Module in Interfaces und Implementations aufteilt. Dann habt ihr aber wieder ganz genau die gleiche Situation wie mit Headern und Cpp-Dateien! Ihr schreibt wieder alles doppelt hin, genau wie früher. Und erwartet nicht, dass es dann funktioniert – damit Linker das Merging von Module Fragments unterstützen, müssen sie beim Name Mangling die Symbole prefixen, und aus einer Funktion inline foo() im Header wird dann ein inline module::foo(), auf das sich der Rest des Projekts beruft, es aber nicht findet, weil es private ist. Aber auch nicht immer, dnn ob das stattfindet, hängt vom Two-Phase-Lookup ab. Herrgott, ich musste extern "C++" einsetzen, um einen Linkerfehler stumm zu kriegen?! WHAT THE FUCK

Ich weiß wirklich nicht, was in den letzten zwei Jahren mit dem Vorschlag passiert ist. Vor zwei Jahren konnte ich ein komplettes Projekt an einem Tag auf Modules umstellen; heute kapituliere ich nach drei Tagen.

Mein Hauptkritikpunkt an C++ ist, dass niemand versteht, wie es funktioniert. Chandler Carruth und John Carmack fassen es hier besser zusammen als ich: https://youtu.be/LJh5QCV4wDg?t=2337

… und diese Komplexität ist durch Module radikal gewachsen.

Nachtrag: Mir fällt gerade auf, dass die Modulsysteme von Java und C# locker auf einer Din-A4-Seite erklärbar sind (für 99 % der Use Cases sogar in einem Satz).

Was das C++-Modulsystem angeht, kommt die Tutorialserie von vector-of-bool auf 47 Din-A4-Seiten(!) und ich krieg’s trotzdem nicht produktiv eingesetzt. Obwohl das wirklich from Scratch entworfen wurde und null Legacy drinsteckt. Das kann man sich nicht ausdenken.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: C++ Modules

Beitrag von Alexander Kornrumpf »

Krishty hat geschrieben: 19.09.2020, 11:39 Nachtrag: Mir fällt gerade auf, dass die Modulsysteme von Java und C# locker auf einer Din-A4-Seite erklärbar sind (für 99 % der Use Cases sogar in einem Satz).
Ich denke das liegt auch daran, dass "Modul" mindestens "Übersetzungseinheit", "Gliederung des Programms für den Programmierer" (vulgo: Datei) und "In sich abgeschlossene funktionale Einheit" bedeuten kann.

Die "Datei"-Dimension ist die am leichtesten zu verstehende und mindestens für Java und Python die einzige, die man wirklich verstehen muss um es produktiv zu benutzen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

In den puren Wahnsinn abgeglitten ist es bei den impliziten Abhängigkeiten. Man nehme an:

  export module foo;

  struct Internal { int var; }; // nicht exportiert

  export Internal makeInternal() { return { 42 }; }


Ein Benutzer des Moduls kann nun makeInternal() aufrufen. Aber dann bekommt er eine Rückgabe vom Typ Internal, und dieser Typ wird nicht vom Modul exportiert!

C#:

Fehler C50050. Das ist nicht erlaubt. Was auch immer man da machen will – es gibt sicher einen Weg, das deutlicher auszudrücken.

Java:

Es ist erlaubt, aber Benutzer werden statt Internal ausschließlich den Basistyp Object erhalten können, weil das alles ist, womit sie was anfangen können, ohne das private zu verletzen. Sie können das Object bei Bedarf ins Modul zurückfüttern, wo es wieder zu Internal gecastet werden kann, falls das nötig ist.

C++:

Also, wir benutzen ein Konzept, das es in C++ schon gibt und keiner benutzen will: Wir unterscheiden zwischen Visibility und Reachability. Der Typ Internal ist für Benutzer des Moduls nicht sichtbar, ich kann also nicht schreiben Internal i = makeInternal();. Was ich aber sehr wohl schreiben kann, ist auto i = makeInternal(); und sogar int lolfu = makeInternal().var;, denn er ist sehr wohl erreichbar! Nun müssen wir dummerweise dem Linker [einem 50 Jahre alten Konzept, das niemand mehr haben will] beibringen, zwischen Reachability und Visibility zu unterscheiden. Führen wir also neben den öffentlichen und privaten Symbolen einen neuen Symbolraum ein, der nicht-öffentliche nicht-private Symbole enthält! Dann müssen wir zwar auch spezifizieren, wie der Linker damit umgeht, wenn Namen kollidieren – aber C++-Programmierer werden’s lieben! Kollisionen zwischen Symbolen finden, die gar nicht exportiert sind, und dann Paragraphen im C++-Standard wälzen um zu erfahren, ob der Fehler im Compiler liegt oder im Code, und aus kryptischen Linker-Fehlern zurückermitteln, wo der Fehler im Quelltext liegt – das lieben die! Und wir müssen’s natürlich auch für enum und namespace spezifizieren, damit jeder sieht, wie viele Gedanken wir uns gemacht haben! Und wir benutzen Jura-Begriffe wie Purview, die zwar außerhalb der Facebook-AGB noch nie ein Schwein gehört hat, aber weil der C++-Standard aus Paragraphen besteht, ist das lustig!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2348
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: C++ Modules

Beitrag von Jonathan »

Alle Jahre wieder: Sind C++ Module schon an dem Punkt angekommen, wo man sie produktiv benutzen will?

Ich bastel gerade an meinem Projekt rum und es kompiliert jetzt schon lange und jedes mal wenn ich 'include' schreibe läuft es mir kalt den Rücken runter. Und seitem ich mir neulich den Includebaum von einer einzelnen Datei angeschaut habe um herauszufinden woher diese dämlichen windows.h includes kommen (und dieser Baum hatte ~1000 Einträge) fände ich funktionierende Module echt mal nice...
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Siehe oben: Du kannst sie in Visual Studio produktiv benutzen. Ich finde sie aber nach meinen Tests schlimmer als #include (und das will was heißen). Habe alle Experimente damit abgebrochen.

Ist vielleicht nur mein Geschmack; ich lasse mich gern von dir überraschen :) Viel Spaß mit Visibility und Reachability!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Jonathan
Establishment
Beiträge: 2348
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: C++ Modules

Beitrag von Jonathan »

Ja, den Beitrag hatte ich vorhin noch gelesen. Dachte, es hätte sich vielleicht etwas getan.
Krishty hat geschrieben: 19.09.2020, 11:39 Dann kommt ihr in die unangenehme Situation, dass Module keine Header #includen dürfen, die auch irgendwo im Rest des Projektes benutzt werden(!!!).
Ist das immer noch so? Soll das so sein? Ich meine, das macht das komplette System doch irgendwie sinnlos? Was ist mit Headern aus der Standardbibliothek? Oder heißt das, dass dann einfach jeder das entsprechende Modul importieren muss und niemand die Datei mehr inkludieren darf?

Klingt jedenfalls alles nicht sehr toll...
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

Die Header aus der Standardbibliothek stellt Visual Studio als Module zur Verfügung … vielleicht verwendet man dann die. Kann das nicht recht beantworten (nutze selber keine Standardbibliothek) :(
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: C++ Modules

Beitrag von NytroX »

Naja, ist aber auch innerhalb von C++ ähnlich oder?
Was ähnliches hatte ich hier schonmal beschrieben:
viewtopic.php?p=60486#p60486

Code: Alles auswählen

auto myfunc(int i) {
	struct returntype {
		int result;
		bool success = true;
	};
	return returntype{ i * 2 }; //geht, weil return type "auto" :-)
}

int main()
{
	auto test1 = myfunc(10); //normal
	if(test1.success)
	{
		auto x = test1.result; //benutzen
	}
	
	auto [result, success] = myfunc(20); //de-struct-uring
	return result;
}
Hat also mMn nicht unbedingt was mit Modulen zu tun. Darum heißen sie ja auch "Voldemort"-Types, weil man sie nicht beim Namen nennen darf :-P
Du kannst aber mal mit decltype versuchen, also so etwa:

Code: Alles auswählen

decltype(makeInternal()) myVar;
using ExportedInternal = decltype(makeInternal()); //hihihi
Hab ich aber noch nicht probiert mit Modulen.

Ist aber ein gängiges Konzept (naja jedenfalls in D, aber die haben auch seit einigen Jahrzehnten brauchbare modules) und auch eigentlich ganz brauchbar für Libraries, wo der Nutzer quasi ein Handle bekommt, aber es nur über die Lib erzeugen soll.
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: C++ Modules

Beitrag von Krishty »

NytroX hat geschrieben: 28.01.2021, 17:02Naja, ist aber auch innerhalb von C++ ähnlich oder? […] Ist aber ein gängiges Konzept
Das war ja auch nicht das Problem. Das Problem war eher:
Krishty hat geschrieben: 17.09.2020, 23:37 error: 'std::strlen' has already been defined

Das Problem scheint zu sein, dass ich zwei Mal #include <cstring> habe – einmal im Modul und einmal in der Übersetzungseinheit, die das Modul benutzt. Dadurch ist die Funktion doppelt deklariert(!).

Ich bin baff weil ich dachte, aus einem Modul würden nur Symbole exportiert werden, die export deklariert sind?! Der Compiler schlägt mir die Definition doppelt als Kandidat vor, und sagt nicht, worin sie sich die beiden Versionen unterscheiden. Ich kann das auch static, inline oder als template deklarieren – es bleibt doppelt definiert.
Es gibt eine Erklärung dafür, und eine Lösung. Ich habe beides verdrängt, weil ich es ehrlich gesagt nur für Verschwendung von Hirnmasse halte. Wenn jemand auf meinen Code schaut, dann muss er die C-Konzepte Deklaration, Definition, #include verstehen. Wenn ich meinen Code auf Module umstelle, muss er die Konzepte Deklaration, Definition, Visibility, Reachability, Fragment, Purview, Global Module Fragment und Private Module Fragment verstehen, und noch mehr, was ich wieder vergessen habe. Ich sehe keinen Grund, warum ich das wählen sollte.

Wie gesagt: Ich würde mich freuen, wenn jemand ein vollständiges Projekt auf Module umstellt und dann hier berichtet, wie’s lief. Vielleicht bin ich ja nur senil und alles ist ganz einfach. Wenn’s gut läuft, ist das Projekt sauberer. Wenn nicht, haben wir alle was gelernt.

Und ja, D hat das besser gemacht. Und C#. Und sogar Java. Nur C++ hat es IMO extrem verkackt, und jetzt klebt es wie Scheiße unter dem Schuh der Sprache, obwohl es uns alle hätte retten können.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Specialist
Establishment
Beiträge: 134
Registriert: 29.08.2003, 14:22
Kontaktdaten:

Re: C++ Modules

Beitrag von Specialist »

Jonathan hat geschrieben: 28.01.2021, 16:11 Ja, den Beitrag hatte ich vorhin noch gelesen. Dachte, es hätte sich vielleicht etwas getan.
Krishty hat geschrieben: 19.09.2020, 11:39 Dann kommt ihr in die unangenehme Situation, dass Module keine Header #includen dürfen, die auch irgendwo im Rest des Projektes benutzt werden(!!!).
Ist das immer noch so? Soll das so sein? Ich meine, das macht das komplette System doch irgendwie sinnlos? Was ist mit Headern aus der Standardbibliothek? Oder heißt das, dass dann einfach jeder das entsprechende Modul importieren muss und niemand die Datei mehr inkludieren darf?

Klingt jedenfalls alles nicht sehr toll...
Scheint mittlerweile nicht mehr so zu sein. Habs gerade mal ausprobiert:

ModulesSample.cpp

Code: Alles auswählen

import MyFirstModule;

#include <iostream>

int main()
{
    std::cout << "This is the module sample" << std::endl;

    M1::hello();
}
MyFirstModule.ixx

Code: Alles auswählen

export module MyFirstModule;

namespace M1
{
	void internalFunction();

	export void hello();
}
MyFirstModule.cpp

Code: Alles auswählen

module;
#include <iostream>

module MyFirstModule;

namespace M1
{
	void internalFunction()
	{
		std::cout << "Start!" << std::endl;
	}

	void hello()
	{
		internalFunction();

		std::cout << "Hello World" << std::endl;
	}
}
Wichtig ist, dass die includes nicht in der Modulschnittstelle sind, sondern in der Implementierung (*.cpp) und im globalen module-Partial liegen (vor dem module MyFirstModule).
Ganz gut gefällt mir die Aufteilung zwischen Module-Interface und Module-Implementierung und dass es auch möglich ist, die Implementierung auf mehrere CPP-Dateien aufzuteilen.

Hier übrigens nochmal schön beschrieben:
https://docs.microsoft.com/de-de/cpp/cp ... w=msvc-160

Ob es komplexere Probleme gibt, kann ich nicht sagen. Das war quasi mein erster Gehversuch mit Modulen :)

Hier nochmal ein etwas erweitertes Beispiel inkl. Klassen:
ModulesSample.zip
(4.6 KiB) 117-mal heruntergeladen
Specialist
Establishment
Beiträge: 134
Registriert: 29.08.2003, 14:22
Kontaktdaten:

Re: C++ Modules

Beitrag von Specialist »

Hat schon jemand herausgefunden, wie man in Visual Studio Modulinterface-Dateien ins Projekt integriert, die nicht im Projektverzeichnis, liegen?
Specialist
Establishment
Beiträge: 134
Registriert: 29.08.2003, 14:22
Kontaktdaten:

Re: C++ Modules

Beitrag von Specialist »

Ich habe nochmal etwas recherchiert und festgestellt, dass man zwar externe Module in seinem Projekt einbinden kann, allerdings müssen diese schon kompiliert sein. Siehe hier (Achtung, mittlerweile heißt die CompilerOption nur noch "/reference" und nicht mehr "/module:reference":
https://docs.microsoft.com/de-de/cpp/bu ... w=msvc-160
Die Option findet sich unter den Projekteigenschaften => C/C++ => Allgemein => Zusätzliche Modulabhängigkeiten

Das funktioniert also leider etwas anders als z.B. die zusätzlichen include-Verzeichnisse.
Eine analoge Option für Module (aka zusätzliche Modulverzeichnisse) scheint es leider nicht zu geben.

Möchte man nicht kompilierte Module (ixx, cpp) im Projekt nutzen, müssen diese Dateien dem Projekt also auf herkömmliche Weise einfach hinzugefügt werden.
Antworten