Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
C++20 zavádí moduly . Modul je sada souborů zdrojového kódu, které jsou kompilovány nezávisle na zdrojových souborech (nebo přesněji na jednotkách překladu), které je importují.
Moduly eliminují nebo snižují řadu problémů spojených s používáním souborů hlaviček. Často zkracují časy kompilace, někdy výrazně. Makra, direktivy preprocesoru a nevyexportované názvy deklarované v modulu nejsou viditelné mimo modul. Nemají žádný vliv na kompilaci jednotky překladu, která modul importuje. Moduly můžete importovat v libovolném pořadí bez problémů s redefinováním maker. Deklarace v importovací překladové jednotce se v importovaném modulu neúčastní řešení přetížení ani vyhledávání názvů. Po zkompilování modulu se výsledky uloží do binárního souboru, který popisuje všechny exportované typy, funkce a šablony. Kompilátor může tento soubor zpracovat mnohem rychleji než soubor hlaviček. Kompilátor ho může znovu použít na každém místě, kde je modul importován do projektu.
Moduly můžete používat vedle souborů hlaviček. Zdrojový soubor C++ může import moduly a také #include hlavičkové soubory. V některých případech můžete importovat soubor hlaviček jako modul, což je rychlejší než použití #include ke zpracování pomocí preprocesoru. Doporučujeme používat moduly v nových projektech místo co nejvíce hlavičkových souborů. U větších stávajících projektů v aktivním vývoji experimentujte s převodem starších hlaviček na moduly. Rozhodněte se podle toho, jestli získáte smysluplné zkrácení doby kompilace.
Pokud chcete porovnat moduly s jinými způsoby importu standardní knihovny, přečtěte si Porovnání jednotek hlaviček, modulů a předkompilovaných hlaviček.
Počínaje sadou Visual Studio 2022 verze 17.5 je import standardní knihovny jako modulu standardizovaný i plně implementovaný v kompilátoru Microsoft C++. Informace o importu standardní knihovny pomocí modulů najdete v tématu Import standardní knihovny C++ pomocí modulů.
Moduly s jedním oddílem
Modul s jedním oddílem je modul, který se skládá z jednoho zdrojového souboru. Rozhraní modulu a implementace jsou ve stejném souboru.
Následující příklad modulu s jedním oddílem ukazuje jednoduchou definici modulu ve zdrojovém souboru s názvem Example.ixx. Rozšíření .ixx je výchozím rozšířením pro soubory rozhraní modulů v sadě Visual Studio. Pokud chcete použít jiné rozšíření, pomocí přepínače /interface ho zkompilujte jako rozhraní modulu. V tomto příkladu soubor rozhraní obsahuje definici funkce i deklaraci. Definice můžete také umístit do jednoho nebo více samostatných souborů implementace modulu, jak je znázorněno v pozdějším příkladu, ale jedná se o příklad modulu s jedním oddílem.
Příkaz export module Example; označuje, že tento soubor je primárním rozhraním modulu s názvem Example. Modifikátor export před int f() indikuje, že tato funkce je viditelná, když jiný program nebo modul importuje Example:
// Example.ixx
export module Example;
#define ANSWER 42
namespace Example_NS
{
int f_internal()
{
return ANSWER;
}
export int f()
{
return f_internal();
}
}
Soubor MyProgram.cpp používá import pro přístup k názvu exportu Example. Název oboru názvů Example_NS je zde viditelný, ale ne všichni jeho členové, protože nejsou exportováni. Také ANSWER makra není viditelná, protože makra se neexportují.
// MyProgram.cpp
import std;
import Example;
using namespace std;
int main()
{
cout << "The result of f() is " << Example_NS::f() << endl; // 42
// int i = Example_NS::f_internal(); // C2039
// int j = ANSWER; //C2065
}
Deklarace import se může zobrazit pouze v globálním rozsahu. Modul a kód, který ho využívá, musí být zkompilovány se stejnými možnostmi kompilátoru.
Gramatika modulu
module-name:
module-name-qualifier-seqvolitidentifier
module-name-qualifier-seq:
identifier.
module-name-qualifier-seqidentifier.
module-partition:
:module-name
module-declaration:
exportvolitmodulemodule-namemodule-partitionvolitattribute-specifier-seqvolit;
module-import-declaration:
exportvolitimportmodule-nameattribute-specifier-seqvolit;
exportvolitimportmodule-partitionattribute-specifier-seqvolit;
exportvolitimportheader-nameattribute-specifier-seqvolit;
Implementace modulů
Rozhraní modulu exportuje název modulu a všechny obory názvů, typy, funkce atd., které tvoří veřejné rozhraní modulu.
Implementace modulu definuje věci exportované modulem.
V nejjednodušší podobě může být modul jedním souborem, který kombinuje rozhraní modulu a implementaci. Implementaci můžete také umístit do jednoho nebo více samostatných souborů implementace modulu, podobně jako .h a .cpp soubory.
U větších modulů můžete části modulu rozdělit do dílčích modulů, které se nazývají oddíly . Každý oddíl se skládá ze souboru rozhraní modulu, který exportuje název oddílu modulu. Oddíl může mít také jeden nebo více souborů implementace oddílu. Modul jako celek má jedno rozhraní primárního modulu, což je veřejné rozhraní modulu. V případě potřeby může rozhraní oddílů exportovat.
Modul se skládá z jedné nebo více jednotek modulu. Jednotka modulu je jednotka překladu (zdrojový soubor), která obsahuje deklaraci modulu. Existuje několik typů jednotek modulu:
- Jednotka rozhraní modulu exportuje název modulu nebo název oddílu modulu. Jednotka rozhraní modulu má v deklaraci modulu
export module. - jednotka implementace modulu neexportuje název modulu ani název oddílu modulu. Jak název napovídá, implementuje modul.
- Jednotka rozhraní primárního modulu exportuje název modulu. V modulu musí existovat pouze jedna jednotka rozhraní primárního modulu.
- Jednotka rozhraní oddílu modulu exportuje název oddílu modulu.
-
jednotka implementace oddílu modulu má název oddílu modulu v deklaraci modulu, ale postrádá klíčové slovo
export.
Klíčové slovo export se používá pouze v souborech rozhraní. Implementační soubor může import jiný modul, ale nemůže export žádná jména. Soubory implementace mohou mít libovolnou příponu.
Moduly, obory názvů a vyhledávání závislé na argumentech
Pravidla pro obory názvů v modulech jsou stejná jako jakýkoli jiný kód. Pokud se exportuje deklarace v rámci oboru názvů, je také implicitně exportován nadřazený obor názvů (s výjimkou členů, které nejsou explicitně exportovány v daném oboru názvů). Pokud je obor názvů explicitně exportován, exportují se všechny deklarace v rámci této definice oboru názvů.
Když kompilátor provádí vyhledávání závislé na argumentech pro řešení přetížení v importované jednotce překladu, bere v úvahu funkce deklarované ve stejné jednotce překladu (včetně rozhraní modulu) jako místa, kde je definován typ argumentů funkce.
Oddíly modulů
Oddíl modulu se podobá modulu s výjimkou:
- Sdílí vlastnictví všech deklarací v celém modulu.
- Všechna jména exportovaná soubory rozhraní oddílu jsou importována a exportována hlavním souborem rozhraní.
- Název oddílu musí začínat názvem modulu a za ním dvojtečka (
:). - Deklarace v libovolném oddílu jsou viditelné v celém modulu.
- Nejsou nutná žádná zvláštní opatření, aby se zabránilo chybám pravidla odr (one-definition-rule). V jednom oddílu můžete deklarovat název (funkce, třída atd.) a definovat ho v jiném oddílu.
Soubor implementace oddílu začíná takto a je interním oddílem z hlediska standardů C++:
module Example:part1;
Soubor rozhraní oddílu začíná takto:
export module Example:part1;
Pokud chcete získat přístup k deklaracím v jiném oddílu, musí ho oddíl importovat. Může ale používat pouze název oddílu, nikoli název modulu:
module Example:part2;
import :part1;
Primární jednotka rozhraní musí importovat a znovu exportovat všechny soubory oddílů rozhraní modulu, například takto:
export import :part1;
export import :part2;
Primární jednotka rozhraní může importovat soubory implementace oddílů, ale nemůže je exportovat. Tyto soubory nesmí exportovat žádné názvy. Toto omezení umožňuje modulu zachovat interní podrobnosti implementace modulu.
Moduly a soubory hlaviček
Soubory hlaviček můžete zahrnout do zdrojového souboru modulu tak, že před deklaraci modulu vložíte direktivu #include. Tyto soubory jsou považovány za fragment globálního modulu . Modul může zobrazit pouze názvy v globálním fragmentu modulu, které jsou v hlavičkách, které explicitně obsahuje. Fragment globálního modulu obsahuje pouze symboly, které se používají.
// MyModuleA.cpp
#include "customlib.h"
#include "anotherlib.h"
import std;
import MyModuleB;
//... rest of file
K řízení importovaných modulů můžete použít tradiční hlavičkový soubor:
// MyProgram.h
#ifdef C_RUNTIME_GLOBALS
import std.compat;
#else
import std;
#endif
Importované soubory hlaviček
Některá záhlaví jsou dostatečně samostatná, aby je bylo možné převést pomocí klíčového slova import. Hlavní rozdíl mezi importovanou hlavičkou a importovaným modulem spočívá v tom, že všechny definice preprocesoru v záhlaví jsou viditelné v importovacím programu hned za příkazem import.
import <vector>;
import "myheader.h";
Viz také
Import standardní knihovny C++ pomocí modulů
module, , importexport
tutoriál pojmenovaných modulů
Porovnání jednotek hlaviček, modulů a předkompilovaných hlaviček