Code Examples From an App Using C++ Modules
We’ve now published a bit more code from our UML Editor Windows app at https://github.com/cadifra/cadifra/tree/2026.5/code.
The code follows our “Recommendations for Using C++ Modules”. In a nutshell these are:
- Prefer small modules
- Only use partitions if you really must
- Avoid using internal partitions
Code from the following packages is now (partially) published:
App: Basic infrastructure for our application (only ixx files)Canvas: Abstract interfaces for drawing (only ixx files)Core: Core abstractions for our UML Editor (complete)Eitor: The top level package of our UML Editor (only ixx files)GraphUtil: Some basic graphical calculations (complete)WinUtil: Lots of basic utilities that deal with the Windows API (complete)d1: Lots of fundamental utilities (complete)xml: Handling of xml diagram files (a few source files)
For each of these we have a Visual Studio project. We use MSBuild (not CMake).

App
The App package contains
a number of modules
App.ComApp.DialogApp.ExecRegistrarApp.ISdiAppApp.Main
There are no partitions in the App package.
Core
The Core package contains
the following modules
Core.AttachCore.ContainerCore.ExceptionsCore.IGridCore.InterfacesCore.MainCore.NamesCore.ObjectIDCore.ObjectRegistryCore.ObjectWithIDCore.Shift
The core Core.Main module
consists of several partitions:
export module Core.Main:CopyRegistryexport module Core.Main:Diagramexport module Core.Main:Elementexport module Core.Main:Selectionexport module Core.Main:Transactionexport module Core.Main:Undoermodule Core.Main:UndoerImpexport module Core.Main:Viewexport module Core.Main:Weight
The reason for using partitions there is, that the classes there use pointers or references to each other. They are very tightly coupled. It would have been possible to put all these classes into a single module unit, but the resulting file would have been too large.
Remember: If you have a pointer (or reference) to a class in a module M, you need to import M. This is a consequence of the attaching rules of modules.
Note that Core.Main:UndoerImp is an internal partition. Altough
we prefer to avoid using internal partitions, this is a case for
using it.
The external partitions of Core.Main are properly exported by
its primary module interface unit Core/Main/Main.ixx:
export module Core.Main;
export import :CopyRegistry;
export import :Diagram;
export import :Element;
export import :Selection;
export import :Transaction;
export import :Undoer;
export import :View;
export import :Weight;
Failing to do so would render the resulting program IF-NDR (“ill-formed,
no diagnostic required”). In our case, the compiler would complain about
a type not beeing defined at places which import Core.Main.
Editor
The Editor package is
the top level package. It has the following modules:
Editor.CmdHandlerDockEditor.InternalsEditor.LicenseInfoEditor.MainEditor.MenuEntryEditor.MessagesEditor.MetafileEditor.NewWindowPlacementEditor.OLEdiagramEditor.PrintEditor.StorageHolderEditor.TransferSetFormatHandlerEditor.UtilEditor.WindowList
The Editor.Main module
contains two partitions:
export module Editor.Main:Diagramexport module Editor.Main:Window
The reason for this is that the classes in Editor.Main:Diagram use pointers
to class Editor::Window in Editor.Main:Window, and the classes in
Editor.Main:Window use pointers to class Editor::Diagram in
Editor.Main:Diagram.
However, there are no internal partitions in Editor.
We kept Editor.Main as small as possible and moved as much as we could
out of it.
Modules from the Editor package are imported in our WinMain.cpp:
import Editor.Main;
import Editor.Util;
import Editor.LicenseInfo;
(last edited 2026-04-26)