10 Modules [module]

10.2 Export declaration [module.interface]

An export-declaration shall appear only at namespace scope and only in the purview of a module interface unit.
An export-declaration shall not appear directly or indirectly within an unnamed namespace or a private-module-fragment.
An export-declaration has the declarative effects of its declaration, declaration-seq (if any), or module-import-declaration.
An export-declaration does not establish a scope and its declaration or declaration-seq shall not contain an export-declaration or module-import-declaration.
A declaration is exported if it is
An exported declaration that is not a module-import-declaration shall declare at least one name.
If the declaration is not within a header unit, it shall not declare a name with internal linkage.
[Example 1:

Source file "a.h":export int x;

Translation unit #1:module; #include "a.h" // error: declaration of x is not in the // purview of a module interface unit export module M; export namespace {} // error: does not introduce any names export namespace { int a1; // error: export of name with internal linkage } namespace { export int a2; // error: export of name with internal linkage } export static int b; // error: b explicitly declared static export int f(); // OK export namespace N { } // OK export using namespace N; // error: does not declare a name — end example]

If the declaration is a using-declaration ([namespace.udecl]) and is not within a header unit, all entities to which all of the using-declarators ultimately refer (if any) shall have been introduced with a name having external linkage.
[Example 2:

Source file "b.h":int f();

Importable header "c.h":int g();

Translation unit #1:export module X; export int h();

Translation unit #2:module; #include "b.h" export module M; import "c.h"; import X; export using ::f, ::g, ::h; // OK struct S; export using ::S; // error: S has module linkage namespace N { export int h(); static int h(int); // #1 } export using N::h; // error: #1 has internal linkage — end example]

[Note 1:
These constraints do not apply to type names introduced by typedef declarations and alias-declarations.
[Example 3: export module M; struct S; export using T = S; // OK, exports name T denoting type S — end example]
— end note]
A redeclaration of an exported declaration of an entity is implicitly exported.
An exported redeclaration of a non-exported declaration of an entity is ill-formed.
[Example 4: export module M; struct S { int n; }; typedef S S; export typedef S S; // OK, does not redeclare an entity export struct S; // error: exported declaration follows non-exported declaration — end example]
A name is exported by a module if it is introduced or redeclared by an exported declaration in the purview of that module.
[Note 2:
Exported names have either external linkage or no linkage; see [basic.link].
Namespace-scope names exported by a module are visible to name lookup in any translation unit importing that module; see [basic.scope.namespace].
Class and enumeration member names are visible to name lookup in any context in which a definition of the type is reachable.
— end note]
[Example 5:

Interface unit of M:export module M; export struct X { static void f(); struct Y { }; }; namespace { struct S { }; } export void f(S); // OK struct T { }; export T id(T); // OK export struct A; // A exported as incomplete export auto rootFinder(double a) { return [=](double x) { return (x + a/x)/2; }; } export const int n = 5; // OK, n has external linkage

Implementation unit of M:module M; struct A { int value; };

Main program:import M; int main() { X::f(); // OK, X is exported and definition of X is reachable X::Y y; // OK, X​::​Y is exported as a complete type auto f = rootFinder(2); // OK return A{45}.value; // error: A is incomplete } — end example]

[Note 3:
Redeclaring a name in an export-declaration cannot change the linkage of the name ([basic.link]).
[Example 6:

Interface unit of M:export module M; static int f(); // #1 export int f(); // error: #1 gives internal linkage struct S; // #2 export struct S; // error: #2 gives module linkage namespace { namespace N { extern int x; // #3 } } export int N::x; // error: #3 gives internal linkage — end example]

— end note]
[Note 4:
Declarations in an exported namespace-definition or in an exported linkage-specification ([dcl.link]) are exported and subject to the rules of exported declarations.
[Example 7: export module M; export namespace N { int x; // OK static_assert(1 == 1); // error: does not declare a name } — end example]
— end note]