Translation unit #1:export module A; export import :Foo; export int baz();
Translation unit #2:export module A:Foo; import :Internals; export int foo() { return 2 * (bar() + 1); }
Translation unit #3:module A:Internals; int bar();
Translation unit #4:module A; import :Internals; int bar() { return baz() - 10; } int baz() { return 30; }
Translation unit #1:module B:Y; / does not implicitly import B int y();
Translation unit #2:export module B; import :Y; / OK, does not create interface dependency cycle int n = y();
Translation unit #3:module B:X1; / does not implicitly import B int &a = n; / error: n not visible here
Translation unit #4:module B:X2; / does not implicitly import B import B; int &b = n; / OK
Translation unit #5:module B; / implicitly imports B int &c = n; / OK — end 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: namespace has 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; / OK — end 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]
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]
Translation unit #1:module M:Part;
Translation unit #2:export module M; export import :Part; / error: exported partition :Part is an implementation unit — end example]
Interface unit of M1:export module M1; import M2;
Interface unit of M2:export module M2; import M3;
Interface unit of M3:export module M3; import M1; / error: cyclic interface dependency M3 →M1 →M2 →M3 — end example]
Source file "foo.h":namespace N { struct X {}; int d(); int e(); inline int f(X, int = d() { return e(); } int g(X); int h(X); }
Module M interface:module; #include "foo.h" export module M; template<typename T> int use_f() { N::X x; / N::X, N, and :: are decl-reachable from use_f return f(x, 123); / N::f is decl-reachable from use_f, / N::e is indirectly decl-reachable from use_f / because it is decl-reachable from N::f, and / N::d is decl-reachable from use_f / because it is decl-reachable from N::f / even though it is not used in this call } template<typename T> int use_g() { N::X x; / N::X, N, and :: are decl-reachable from use_g return g((T(), x)); / N::g is not decl-reachable from use_g } template<typename T> int use_h() { N::X x; / N::X, N, and :: are decl-reachable from use_h return h((T(), x)); / N::h is not decl-reachable from use_h, but / N::h is decl-reachable from use_h<int> } int k = use_h<int>(); / use_h<int> is decl-reachable from k, so / N::h is decl-reachable from k
Module M implementation:module M; int a = use_f<int>(); / OK int b = use_g<int>(); / error: no viable function for call to g; / g is not decl-reachable from purview of / module M's interface, so is discarded int c = use_h<int>(); / OK — end example]
Translation unit #1:export module stuff; export template<typename T, typename U> void foo(T, U u) { auto v = u; } export template<typename T, typename U> void bar(T, U u) { auto v = *u; }
Translation unit #2:export module M1; import "defn.h"; / provides struct X {}; import stuff; export template<typename T> void f(T t) { X x; foo(t, x); }
Translation unit #3:export module M2; import "decl.h"; / provides struct X; (not a definition) import stuff; export template<typename T> void g(T t) { X *x; bar(t, x); }
Translation unit #4:import M1; import M2; void test() { f(0); g(0); }
Translation unit #1:export module M:A; export struct B;
Translation unit #2:module M:B; struct B { operator int(); };
Translation unit #3:module M:C; import :A; B b1; / error: no reachable definition of struct B
Translation unit #4:export module M; export import :A; import :B; B b2; export void f(B b = B();
Translation unit #5:import M; B b3; / error: no reachable definition of struct B void g() { f(); } / error: no reachable definition of struct B — end example]
Translation unit #1:export module A; struct X {}; export using Y = X;
Translation unit #2:import A; Y y; / OK, definition of X is reachable X x; / error: X not visible to unqualified lookup — end example]