10 Modules [module]

10.2 Export declaration [module.interface]

export-declaration:
export declaration
export { declaration-seq }
export-keyword module-import-declaration
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
:

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 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
:

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
:
These constraints do not apply to type names introduced by typedef declarations and alias-declarations.
[Example
:
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
:
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
:
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
:

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
:
Redeclaring a name in an export-declaration cannot change the linkage of the name ([basic.link]).
[Example
:

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