Home > Software engineering >  What is the difference between non-export declarations and declarations in private module fragment?
What is the difference between non-export declarations and declarations in private module fragment?

Time:03-02

On cppreference.com about modules it says about export:

Module interface units can export declarations and definitions, which can be imported by other translation units. [ … ]
All declarations and definitions exported in the module interface units of the given named module will be available in the translation unit using the import declaration.

Guessing from that, I'd export everything that users of the module want or need to use it. Everything not exported is an implementation detail of the module and none of the importers’ concern.

It also tells me that

a private module fragment [ … ] allows a module to be represented as a single translation unit without making all of the contents of the module reachable to importers.

What is the difference between putting something in the private module fragment than to just not exporting it? I guess there’s a difference between “available in the translation unit using the import declaration” and “reachable to importers”. But what is that difference from a practical point of view? As a guideline, when would I put something in the private module fragment and when just not exporting it?

(Highlight inside quotes by me.)

CodePudding user response:

What is the difference between putting something in the private module fragment than to just not exporting it

The principle difference in terms of implementation is that non-exported definitions that are in a module interface can be imported by other pieces of code that are part of the same module (implementation units and other interface units of the module). They will have access to those declarations even though you don't export them. As such, those declarations must live (to some degree) in whatever file the compiler uses for that module.

By contrast, private module fragment code doesn't contribute to any accessible interface of the module. It acts like a module implementation unit.

But here's the thing: you wouldn't be able to tell the difference. Why? If the primary module interface has a private module fragment, there cannot be any other files that are part of the same module. That's expressly forbidden. The private module fragment as a tool exists to support cases where you want to ship a complete module as a single file. There's nothing that a private module fragment can do which a module implementation unit cannot.

CodePudding user response:

The answer is explained in more detail on cppreference

Quoting it here for completeness of the answer.

Private module fragment

Primary module interface unit can be suffixed by a private module fragment, which allows a module to be represented as a single translation unit without making all of the contents of the module reachable to importers.


module : private ;

declaration-seq(optional)

Private module fragment ends the portion of the module interface unit that can affect the behavior of other translation units. If a module unit contains a private module fragment, it will be the only module unit of its module.

export module foo;
export int f();
 
module :private; // ends the portion of the module interface unit that
                 // can affect the behavior of other translation units
                 // starts a private module fragment
 
int f() {        // definition not reachable from importers of foo
    return 42;
}

i.e. you can thus both export the declaration and hide the definition.

The use case is explained here

Thanks to a private module fragment, you can implement a module in one file and declare its last part as its implementation using module :private;. Consequently, a modification of the private module fragment does not cause recompilation.

  • Related