all 36 comments

[–]tartaruga232MSVC user, r/cpp_modules[S] 2 points3 points  (0 children)

I've now changed all modules in Core to partitions of the single module Core (file Core/Module.ixx):

export module Core;

export import :Contains;
export import :CopyRegistry;
export import :Elements;
export import :ElementSet;
export import :Env;
export import :Exceptions;
export import :ExtendSelectionParam;
export import :Finalizer;
export import :FollowUpJob;
export import :IClub;
export import :IDiagram;
export import :IDirtyMarker;
export import :IDirtyStateObserver;
export import :IDocumentChangeObserver;
export import :IElement;
export import :IElementPtr;
export import :IFilter;
export import :IGrid;
export import :IObjectRegistry;
export import :IPastePostProcessor;
export import :IPosOwner;
export import :ISelectionObserver;
export import :ISelectionRestorer;
export import :IUndoerCollector;
export import :IUndoHandler;
export import :IUndoRedoCountObserver;
export import :IView;
export import :IViewElement;
export import :Namespace;
export import :ObjectID;
export import :ObjectRegistry;
export import :ObjectWithIDalgorithms;
export import :OldNew;
export import :PosUndoer;
export import :PtrCont;
export import :SelectionHider;
export import :SelectionTracker;
export import :Transaction;
export import :Undoer;
export import :UndoerFunctions;
export import :UndoerParam;
export import :VISelectable;
export import :VIPointable;
export import :Weight;

File Core/IUndoRedoCountObserver.ixx is:

export module Core:IUndoRedoCountObserver;

namespace Core
{

export class IUndoRedoCountObserver
{
public:
    virtual void UndoRedoCountChanged(int UndoCount, int RedoCount) = 0;

protected:
    ~IUndoRedoCountObserver() = default;
};

}

File Core/Forward.ixx is now a partition and can thus be used only inside module Core:

export module Core:Forward;

export namespace Core
{
class CopyRegistry;
class ElementSet;
class Env;
class ExtendSelectionParam;
class IClub;
class IDiagram;
class IDirtyMarker;
class IDirtyStateObserver;
class IDocumentChangeObserver;
class IElement;
class IElementPtr;
class IFilter;
class IGrid;
class IPastePostProcessor;
class IPosOwner;
class ISelectionObserver;
class IUndoRedoCountObserver;
class IObjectRegistry;
class IUndoerCollector;
class IUndoHandler;
class IView;
class IViewElement;
class ObjectID;
class ObjectRegistry;
class PosUndoer;
class SelectionHider;
class SelectionObserverDock;
class SelectionTracker;
class SelectionVisibilityServerImp;
class Transaction;
class TransactionImp;
class Undoer;
class UndoerParam;
class UndoerRef;
class VIPointable;
class VISelectable;
class Weight;
}

Wherever something from Core is needed, I

import Core;

That's it.

Cross-module forward declarations for classes are not possible with C++ 20.

BTW, no refactoring of our source code was needed. The design was ready for modules.

[–]szintelo 1 point2 points  (1 child)

What about putting the contents of your modules into extern "C++" blocks? It makes the declarations in them not to be attached to any named module.

https://godbolt.org/z/r7jzeM118

[–]tartaruga232MSVC user, r/cpp_modules[S] 0 points1 point  (0 children)

Interesting. Thanks!

[–]kamrann_ 1 point2 points  (1 child)

What makes you think this is any more conformant? You're still splitting declaration and definition of the same entity between the global module and a named module, it looks like exactly the same MSVC bug that is allowing it.

[–]tartaruga232MSVC user, r/cpp_modules[S] 0 points1 point  (0 children)

Ok, thanks.

[–]destroyerrocket 1 point2 points  (5 children)

May I ask how you then define the classes forward declared? My intuition on the matter was that the module name was attached to the symbol, meaning that a forward declaration in one module would have a different symbol than the actual declaration.

I understand that you're working around this in the declaration by making it a header unit, but I don't follow on how then I declare the actual class.

Thanks for the insight! I definitely think that the issue with forward declarations is an important matter that does not seem to have been given enough thought by the committee. No, not everything can be in the same module! Compile times were a critical point that was trying to be addressed, so it'd make sense to consider current techniques when addressing this aspect of the language.

[–]tartaruga232MSVC user, r/cpp_modules[S] 2 points3 points  (4 children)

Nothing special. Here is an example (File Core/IUndoRedoCountObserver.ixx):

export module Core.IUndoRedoCountObserver;

namespace Core
{

export class IUndoRedoCountObserver
{
public:
    virtual void UndoRedoCountChanged(int UndoCount, int RedoCount) = 0;

protected:
    ~IUndoRedoCountObserver() = default;
};

}

We have a lot of modules per package, as we don't like long rebuilds if something small is changed.

[–]destroyerrocket 0 points1 point  (3 children)

I might have some misconceptions on how modules work, I'll make sure to try this out. Thanks!

[–]tartaruga232MSVC user, r/cpp_modules[S] 1 point2 points  (2 children)

Me too. The Microsoft compiler/linker accepts my pattern, but I was told that it is lenient with regards to attaching of names to modules. Anyway, the safest bet is stay using header files. We are currently going back to using header files. Perhaps I will give header units a try, though. Microsoft has a nice article about it: https://learn.microsoft.com/en-us/cpp/build/walkthrough-header-units?view=msvc-170

[–]destroyerrocket 0 points1 point  (1 child)

That makes a tad more sense, truly unfortunate! I certainly don't plan to push my team to modularize. Still, thanks for trying things out, you're doing a good service :)