Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Modules(since C++20)

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
       

      Most C++ projects use multiple translation units, and so they need to sharedeclarations anddefinitions across those units. The usage ofheaders is prominent for this purpose, an example being thestandard library whose declarations can be provided byincluding the corresponding header.

      Modules are a language feature to share declarations and definitions across translation units.They are an alternative to some use cases of headers.

      Modules are orthogonal tonamespaces.

      // helloworld.cppexport module helloworld;// module declaration import<iostream>;// import declaration exportvoid hello()// export declaration{std::cout<<"Hello world!\n";}
      // main.cppimport helloworld;// import declaration int main(){    hello();}

      Contents

      [edit] Syntax

      export(optional)modulemodule-name module-partition (optional)attr (optional); (1)
      exportdeclaration (2)
      export {declaration-seq (optional)} (3)
      export(optional)importmodule-name attr (optional); (4)
      export(optional)importmodule-partition attr (optional); (5)
      export(optional)importheader-name attr (optional); (6)
      module; (7)
      module : private; (8)
      1) Module declaration. Declares that the current translation unit is amodule unit.
      2,3) Export declaration. Export all namespace-scope declarations indeclaration ordeclaration-seq.
      4,5,6) Import declaration. Import a module unit/module partition/header unit.
      7) Starts aglobal module fragment.
      8) Starts aprivate module fragment.

      [edit]Module declarations

      A translation unit may have a module declaration, in which case it is considered amodule unit.Themodule declaration, if provided, must be the first declaration of the translation unit (excepted theglobal module fragment, which is covered later on). Each module unit is associated to amodule name (and optionally a partition), provided in the module declaration.

      export(optional)modulemodule-name module-partition (optional)attr (optional);

      The module name consists of one or more identifiers separated by dots (for example:mymodule,mymodule.mysubmodule,mymodule2...). Dots have no intrinsic meaning, however they are used informally to represent hierarchy.

      If any identifier in the module name or module partition is defined as anobject-like macro, the program is ill-formed.

      Anamed module is the collection of module units with the same module name.

      Module units whose declaration has the keywordexport are termedmodule interface units; all other module units are termedmodule implementation units.

      For every named module, there must be exactly one module interface unit that specifies no module partition; this module unit is termed theprimary module interface unit. Its exported content will be available when importing the corresponding named module.

      // (each line represents a separate translation unit) export module A;// declares the primary module interface unit for named module 'A'module A;// declares a module implementation unit for named module 'A'module A;// declares another module implementation unit for named module 'A'export module A.B;// declares the primary module interface unit for named module 'A.B'module A.B;// declares a module implementation unit for named module 'A.B'

      [edit]Exporting declarations and definitions

      Module interface units can export declarations (including definitions), which can be imported by other translation units. To export a declaration, either prefix it with theexport keyword, or else place it inside anexport block.

      exportdeclaration
      export {declaration-seq (optional)}
      export module A;// declares the primary module interface unit for named module 'A' // hello() will be visible by translations units importing 'A'exportcharconst* hello(){return"hello";}  // world() will NOT be visible.charconst* world(){return"world";} // Both one() and zero() will be visible.export{int one(){return1;}int zero(){return0;}} // Exporting namespaces also works: hi::english() and hi::french() will be visible.exportnamespace hi{charconst* english(){return"Hi!";}charconst* french(){return"Salut!";}}

      [edit]Importing modules and header units

      Modules are imported via animport declaration:

      export(optional)importmodule-name attr (optional);

      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.

      Import declarations can be exported in a module interface unit. That is, if moduleB export-importsA, then importingB will also make visible all exports fromA.

      In module units, all import declarations (including export-imports) must be grouped after the module declaration and before all other declarations.

      /////// A.cpp (primary module interface unit of 'A')export module A; exportcharconst* hello(){return"hello";} /////// B.cpp (primary module interface unit of 'B')export module B; export import A; exportcharconst* world(){return"world";} /////// main.cpp (not a module unit)#include <iostream>import B; int main(){std::cout<< hello()<<' '<< world()<<'\n';}

      #include should not be used in a module unit (outside theglobal module fragment), because all included declarations and definitions would be considered part of the module. Instead, headers can also be imported asheader units with animport declaration:

      export(optional)importheader-name attr (optional);

      A header unit is a separate translation unit synthesized from a header. Importing a header unit will make accessible all its definitions and declarations. Preprocessor macros are also accessible (because import declarations are recognized by the preprocessor).

      However, contrary to#include, preprocessing macros already defined at the point of the import declaration will not affect the processing of the header. This may be inconvenient in some cases (some headers use preprocessing macros as a form of configuration), in which case the usage ofglobal module fragment is needed.

      /////// A.cpp (primary module interface unit of 'A')export module A; import<iostream>;export import<string_view>; exportvoid print(std::string_view message){std::cout<< message<<std::endl;} /////// main.cpp (not a module unit)import A; int main(){std::string_view message="Hello, world!";    print(message);}

      [edit]Global module fragment

      Module units can be prefixed by aglobal module fragment, which can be used to include headers when importing the headers is not possible (notably when the header uses preprocessing macros as configuration).

      module;

      preprocessing-directives (optional)

      module-declaration

      If a module-unit has a global module fragment, then its first declaration must bemodule;. Then, onlypreprocessing directives can appear in the global module fragment. Then, a standard module declaration marks the end of the global module fragment and the start of the module content.

      /////// A.cpp (primary module interface unit of 'A')module; // Defining _POSIX_C_SOURCE adds functions to standard headers,// according to the POSIX standard.#define _POSIX_C_SOURCE 200809L#include <stdlib.h> export module A; import<ctime>; // Only for demonstration (bad source of randomness).// Use C++ <random> instead.exportdouble weak_random(){std::timespec ts;std::timespec_get(&ts,TIME_UTC);// from <ctime> // Provided in <stdlib.h> according to the POSIX standard.    srand48(ts.tv_nsec); // drand48() returns a random number between 0 and 1.return drand48();} /////// main.cpp (not a module unit)import<iostream>;import A; int main(){std::cout<<"Random value between 0 and 1: "<< weak_random()<<'\n';}

      [edit]Private module fragment

      Primary module interface unit can be suffixed by aprivate 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 aprivate module fragment, it will be the only module unit of its module.

      export module foo; exportint 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{return42;}

      [edit]Module partitions

      A module can havemodule partition units. They are module units whose module declarations include a module partition, which starts with a colon: and is placed after the module name.

      export module A:B;// Declares a module interface unit for module 'A', partition ':B'.

      A module partition represents exactly one module unit (two module units cannot designate the same module partition). They are visible only from inside the named module (translation units outside the named module cannot import a module partition directly).

      A module partition can be imported by module units of the same named module.

      export(optional)importmodule-partition attr (optional);
      /////// A-B.cppexport module A:B;... /////// A-C.cppmodule A:C;... /////// A.cppexport module A; import:C;export import:B; ...

      All definitions and declarations in a module partition are visible by the importing module unit, whether exported or not.

      Module partitions can be module interface units (when their module declarations haveexport). They must be export-imported by the primary module interface unit, and their exported statements will be visible when the module is imported.

      export(optional)importmodule-partition attr (optional);
      ///////  A.cppexport module A;// primary module interface unit export import:B;// Hello() is visible when importing 'A'.import:C;// WorldImpl() is now visible only for 'A.cpp'.// export import :C; // ERROR: Cannot export a module implementation unit. // World() is visible by any translation unit importing 'A'.exportcharconst* World(){return WorldImpl();}
      /////// A-B.cppexport module A:B;// partition module interface unit // Hello() is visible by any translation unit importing 'A'.exportcharconst* Hello(){return"Hello";}
      /////// A-C.cppmodule A:C;// partition module implementation unit // WorldImpl() is visible by any module unit of 'A' importing ':C'.charconst* WorldImpl(){return"World";}
      /////// main.cppimport A;import<iostream>; int main(){std::cout<< Hello()<<' '<< World()<<'\n';// WorldImpl(); // ERROR: WorldImpl() is not visible.}

      [edit]Module ownership

      In general, if a declaration appears after the module declaration in a module unit, it isattached to that module.

      If a declaration of an entity is attached to a named module, that entity can only be defined in that module. All declarations of such an entity must be attached to the same module.

      If a declaration is attached to a named module, and it is not exported, the declared name hasmodule linkage.

      export module lib_A; int f(){return0;}// f has module linkageexportint x= f();// x equals 0
      export module lib_B; int f(){return1;}// OK, f in lib_A and f in lib_B refer to different entitiesexportint y= f();// y equals 1

      Iftwo declarations of an entity are attached to different modules, the program is ill-formed; no diagnostic is required if neither is reachable from the other.

      /////// decls.hint f();// #1, attached to the global moduleint g();// #2, attached to the global module
      /////// Module interface of Mmodule;#include "decls.h"export module M;exportusing::f;// OK, does not declare an entity, exports #1int g();// Error: matches #2, but attached to Mexportint h();// #3exportint k();// #4
      /////// Other translation unitimport M;staticint h();// Error: matches #3int k();// Error: matches #4

      The following declarations are not attached to any named module (and thus the declared entity can be defined outside the module):

      export module lib_A; namespace ns// ns is not attached to lib_A.{    exportextern"C++"int f();// f is not attached to lib_A.extern"C++"int g();// g is not attached to lib_A.    exportint h();// h is attached to lib_A.}// ns::h must be defined in lib_A, but ns::f and ns::g can be defined elsewhere (e.g.// in a traditional source file).

      [edit]Notes

      Feature-test macroValueStdFeature
      __cpp_modules201907L(C++20)Modules — core language support
      __cpp_lib_modules202207L(C++23)Standard library modulesstd andstd.compat

      [edit]Keywords

      private,module,import,export

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 2732C++20it was unclear whether importable headers can
      react to preprocessor state from the point of import
      no reaction
      P3034R1C++20module names and module partitions could
      contain identifiers defined as object-like macros
      prohibited
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/modules&oldid=176071"

      [8]ページ先頭

      ©2009-2025 Movatter.jp