9.8 KiB
[module.global.frag]
10 Modules [module]
10.4 Global module fragment [module.global.frag]
global-module-fragment:
module-keyword ; declaration-seqopt
[Note 1:
Prior to phase 4 of translation, only preprocessing directives can appear in the declaration-seq ([cpp.pre]).
â end note]
A global-module-fragment specifies the contents of theglobal module fragment for a module unit.
The global module fragment can be used to provide declarations that are attached to the global module and usable within the module unit.
A declaration D is decl-reachable from a declaration S in the same translation unit if
D does not declare a function or function template andS contains anid-expression,namespace-name,type-name,template-name, orconcept-name naming D, or
D declares a function or function template that is named by an expression ([basic.def.odr]) appearing in S, or
S contains a dependent call E ([temp.dep]) and D is found by any name lookup performed for an expression synthesized from E by replacing each type-dependent argument or operand with a value of a placeholder type with no associated namespaces or entities, or [Note 2: This includes the lookup for operator== performed when considering rewriting an != expression, the lookup for operator<=> performed when considering rewriting a relational comparison, and the lookup for operator!= when considering whether an operator== is a rewrite target. â end note]
S contains an expression that takes the address of an overload set ([over.over]) that contains D and for which the target type is dependent, or
there exists a declaration M that is not a namespace-definition for which M is decl-reachable from S and either
D is decl-reachable from M, or
D and M declare the same entity, and D neither is a friend declaration nor inhabits a block scope, or
D declares a namespace N and M is a member of N, or
one of D and M declares a class or class template C and the other declares a member or friend of C, or
one of D and M declares an enumeration E and the other declares an enumerator of E, or
D declares a function or variable and M is declared in D,86 or
one of D and M declares a template and the other declares a partial or explicit specialization or an implicit or explicit instantiation of that template, or
M declares a class template and D is a deduction guide for that template, or
one of D and M declares a class or enumeration type and the other introduces a typedef name for linkage purposes for that type.
In this determination, it is unspecified
whether a reference to analias-declaration,typedef declaration,using-declaration, ornamespace-alias-definition is replaced by the declarations they name prior to this determination,
whether a simple-template-id that does not denote a dependent type and whose template-name names an alias template is replaced by its denoted type prior to this determination,
whether a decltype-specifier that does not denote a dependent type is replaced by its denoted type prior to this determination,
whether a non-value-dependent constant expression is replaced by the result of constant evaluation prior to this determination, and
whether a splice-expression, a splice-type-specifier, a splice-scope-specifier, or any splice-specifier orsplice-specialization-specifier outside of the preceding is replaced in any non-dependent context by the construct that it designates prior to this determination.
A declaration D in a global module fragment of a module unit is discarded if D is not decl-reachable from any declaration in the declaration-seq of the translation-unit.
[Note 3:
A discarded declaration is neither reachable nor visible to name lookup outside the module unit, nor in template instantiations whose points of instantiation ([temp.point]) are outside the module unit, even when the instantiation context ([module.context]) includes the module unit.
â end note]
[Example 1: const int size = 2;int ary1[size]; // unspecified whether size is decl-reachable from ary1constexpr int identity(int x) { return x; }int ary2[identity(2)]; // unspecified whether identity is decl-reachable from ary2template struct S;template<typename, int> struct S2;constexpr int g(int);
template<typename T, int N> S<S2<T, g(N)>> f(); // S, S2, g, and :: are decl-reachable from ftemplatevoid h() noexcept(g(N) == N); // g and :: are decl-reachable from h â end example]
[Example 2:
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 int use_f() { N::X x; // N::X, N, and :: are decl-reachable from use_freturn 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 int use_g() { N::X x; // N::X, N, and :: are decl-reachable from use_greturn g((T(), x)); // N::g is not decl-reachable from use_g}template int use_h() { N::X x; // N::X, N, and :: are decl-reachable from use_hreturn h((T(), x)); // N::h is not decl-reachable from use_h, but// N::h is decl-reachable from use_h}int k = use_h(); // use_h is decl-reachable from k, so// N::h is decl-reachable from k
Module M implementation:module M;int a = use_f(); // OKint b = use_g(); // error: no viable function for call to g;// g is not decl-reachable from purview of// module M's interface, so is discardedint c = use_h(); // OK â end example]
A declaration can appear within a lambda-expression in the initializer of a variable.