C++에서의 모듈 개요

C++20에는 모듈이 도입되었습니다. 모듈은 소스 파일을 가져오는 소스 파일(또는 보다 정확하게 번역 단위)과 독립적으로 컴파일되는 소스 코드 파일 집합입니다.

모듈은 헤더 파일 사용과 관련된 많은 문제를 제거하거나 줄입니다. 종종 컴파일 시간을 크게 줄입니다. 모듈에 선언된 매크로, 전처리기 지시문 및 지원되지 않는 이름은 모듈 외부에 표시되지 않습니다. 모듈을 가져오는 번역 단위의 컴파일에는 영향을 주지 않습니다. 매크로 재정의에 대한 우려 없이 모듈을 순서대로 가져올 수 있습니다. 가져오기 변환 단위의 선언은 가져온 모듈에서 오버로드 확인 또는 이름 조회에 참여하지 않습니다. 모듈이 한 번 컴파일되면 결과는 내보낸 모든 형식, 함수 및 템플릿을 설명하는 이진 파일에 저장됩니다. 컴파일러는 헤더 파일보다 훨씬 빠르게 해당 파일을 처리할 수 있습니다. 또한 컴파일러는 프로젝트에서 모듈을 가져오는 모든 위치에서 다시 사용할 수 있습니다.

모듈을 헤더 파일과 함께 사용할 수 있습니다. C++ 소스 파일은 모듈들을 포함할 수 있고, 또한 헤더 파일들도 포함할 수 있습니다. 경우에 따라 헤더 파일을 모듈로 가져올 수 있습니다. 이 모듈은 전처리기로 처리하는 데 사용하는 #include 것보다 빠릅니다. 헤더 파일 대신 새 프로젝트에서 모듈을 가능한 한 많이 사용하는 것이 좋습니다. 현재 개발 중인 대규모 기존 프로젝트의 경우 레거시 헤더를 모듈로 변환하는 방법을 실험합니다. 컴파일 시간이 의미 있게 감소하는지 여부에 따라 채택 여부를 결정하십시오.

모듈을 표준 라이브러리를 가져오는 다른 방법과 대조하려면 헤더 단위, 모듈 및 미리 컴파일된 헤더 비교를 참조하세요.

Visual Studio 2022 버전 17.5부터 표준 라이브러리를 모듈로 가져오는 것은 Microsoft C++ 컴파일러에서 표준화되고 완전히 구현됩니다. 모듈을 사용하여 표준 라이브러리를 가져오는 방법을 알아보려면 모듈을 사용하여 C++ 표준 라이브러리 가져오기를 참조하세요.

단일 파티션 모듈

단일 파티션 모듈은 단일 소스 파일로 구성된 모듈입니다. 모듈 인터페이스 및 구현은 동일한 파일에 있습니다.

다음 단일 파티션 모듈 예제에서는 소스 파일의 간단한 모듈 정의를 보여 냅니다 Example.ixx. 확장은 .ixx Visual Studio의 모듈 인터페이스 파일에 대한 기본 확장입니다. 다른 확장을 사용하려면 /interface 스위치를 사용하여 모듈 인터페이스로 컴파일합니다. 이 예제에서 인터페이스 파일에는 함수 정의와 선언이 모두 포함됩니다. 이후 예제와 같이 하나 이상의 개별 모듈 구현 파일에 정의를 배치할 수도 있지만 단일 파티션 모듈의 예입니다.

이 문은 export module Example; 이 파일이 호출 Example된 모듈의 기본 인터페이스임을 나타냅니다. 앞 exportint f() 한정자는 다른 프로그램 또는 모듈을 가져올 때 이 함수가 표시된다는 것을 나타냅니다.Example

// Example.ixx
export module Example;

#define ANSWER 42

namespace Example_NS
{
   int f_internal()
   {
     return ANSWER;
   }

   export int f()
   {
     return f_internal();
   }
}

파일 MyProgram.cppimport에서 내보낸 이름에 액세스하기 위해 Example를 사용합니다. 네임스페이스 이름은 Example_NS 여기에 표시되지만 일부 멤버는 내보내지 않으므로 표시되지 않습니다. 또한 매크로 ANSWER 는 내보내지 않으므로 표시되지 않습니다.

// 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
}

import 선언은 전역 범위에만 나타날 수 있습니다. 모듈과 모듈을 사용하는 코드는 동일한 컴파일러 옵션으로 컴파일되어야 합니다.

모듈 문법

module-name:
module-name-qualifier-seq 선택identifier

module-name-qualifier-seq:
identifier .
module-name-qualifier-seq identifier .

module-partition:
: module-name

module-declaration:
export 선택modulemodule-namemodule-partition선택attribute-specifier-seq선택;

module-import-declaration:
export 선택importmodule-nameattribute-specifier-seq선택;
export 선택importmodule-partitionattribute-specifier-seq선택;
export 선택importheader-nameattribute-specifier-seq선택;

모듈 구현

모듈 인터페이스는 모듈의 공용 인터페이스를 구성하는 모듈 이름과 모든 네임스페이스, 형식, 함수 등을 내보냅니다.
모듈 구현은 모듈에서 내보낸 항목을 정의합니다.
가장 간단한 형식에서 모듈은 모듈 인터페이스와 구현을 결합하는 단일 파일일 수 있습니다. 구현을 .h.cpp 파일이 하는 것처럼 하나 이상의 개별 모듈 구현 파일에 넣을 수도 있습니다.

더 큰 모듈의 경우 모듈의 일부를 파티션이라는 하위 모듈로 분할할 수 있습니다. 각 파티션은 모듈 파티션 이름을 내보내는 모듈 인터페이스 파일로 구성됩니다. 파티션에는 하나 이상의 파티션 구현 파일이 있을 수도 있습니다. 모듈 전체에는 모듈의 공용 인터페이스인 하나의 기본 모듈 인터페이스가 있습니다. 원하는 경우 파티션 인터페이스를 내보낼 수 있습니다.

모듈은 하나 이상의 모듈 단위로 구성됩니다. 모듈 단위는 모듈 선언을 포함하는 변환 단위(원본 파일)입니다. 모듈 단위에는 다음과 같은 몇 가지 유형이 있습니다.

  • 모듈 인터페이스 단위는 모듈 이름 또는 모듈 파티션 이름을 내보냅니다. 모듈 인터페이스 단위는 export module 모듈 선언에 있습니다.
  • 모듈 구현 단위는 모듈 이름 또는 모듈 파티션 이름을 내보내지 않습니다. 이름에서 알 수 있듯이 모듈을 구현합니다.
  • 기본 모듈 인터페이스 단위는 모듈 이름을 내보냅니다. 모듈에는 하나의 기본 모듈 인터페이스 단위가 하나만 있어야 합니다.
  • 모듈 파티션 인터페이스 단위는 모듈 파티션 이름을 내보냅니다.
  • 모듈 파티션 구현 단위에는 모듈 선언에 모듈 파티션 이름이 있지만 키워드는 없습니다export.

export 키워드는 인터페이스 파일에서만 사용됩니다. 구현 파일은 다른 모듈을 참조할 수 import 있지만, 어떠한 이름도 가져올 수는 없습니다 export. 구현 파일에는 확장명이 있을 수 있습니다.

모듈, 네임스페이스 및 인수 종속 조회

모듈의 네임스페이스에 대한 규칙은 다른 코드와 동일합니다. 네임스페이스 내의 선언을 내보내면 바깥쪽 네임스페이스(해당 네임스페이스에서 명시적으로 내보내지 않은 멤버 제외)도 암시적으로 내보내집니다. 네임스페이스를 명시적으로 내보내면 해당 네임스페이스 정의 내의 모든 선언이 내보내집니다.

컴파일러가 가져오기 변환 단위에서 오버로드 확인에 대해 인수 종속 조회를 수행하는 경우 함수의 인수 형식이 정의된 위치와 동일한 변환 단위(모듈 인터페이스 포함)에 선언된 함수를 고려합니다.

모듈 파티션

모듈 파티션은 다음을 제외하고 모듈과 유사합니다.

  • 전체 모듈에서 모든 선언의 소유권을 공유합니다.
  • 파티션 인터페이스 파일에서 내보낸 모든 이름은 기본 인터페이스 파일에서 가져오고 내보냅니다.
  • 파티션의 이름은 모듈 이름 뒤에 콜론(:)으로 시작해야 합니다.
  • 파티션의 선언은 전체 모듈 내에 표시됩니다.
  • ODR(단일 정의 규칙) 오류를 방지하기 위해 특별한 예방 조치가 필요하지 않습니다. 한 파티션에서 이름(함수, 클래스 등)을 선언하고 다른 파티션에서 정의할 수 있습니다.

파티션 구현 파일은 다음과 같이 시작되며 C++ 표준 관점에서 내부 파티션입니다.

module Example:part1;

파티션 인터페이스 파일은 다음과 같이 시작됩니다.

export module Example:part1;

다른 파티션의 선언에 액세스하려면 해당 파티션을 임포트해야 합니다. 그러나 모듈 이름이 아닌 파티션 이름만 사용할 수 있습니다.

module Example:part2;
import :part1;

기본 인터페이스 단위는 다음과 같이 모듈의 모든 인터페이스 파티션 파일을 가져오고 다시 내보내야 합니다.

export import :part1;
export import :part2;

기본 인터페이스 단위는 파티션 구현 파일을 가져올 수 있지만 내보낼 수는 없습니다. 이러한 파일은 이름을 내보낼 수 없습니다. 이 제한을 사용하면 모듈에서 구현 세부 정보를 모듈 내부에 유지할 수 있습니다.

모듈 및 헤더 파일

모듈 선언 앞에 지시문을 배치 #include 하여 모듈 소스 파일에 헤더 파일을 포함할 수 있습니다. 이러한 파일은 전역 모듈 조각에 있는 것으로 간주됩니다. 모듈은 명시적으로 포함하는 헤더에 있는 전역 모듈 조각의 이름만 볼 수 있습니다. 전역 모듈 조각에는 사용되는 기호만 포함됩니다.

// MyModuleA.cpp

#include "customlib.h"
#include "anotherlib.h"

import std;
import MyModuleB;

//... rest of file

기존 헤더 파일을 사용하여 가져올 모듈을 제어할 수 있습니다.

// MyProgram.h
#ifdef C_RUNTIME_GLOBALS
import std.compat;
#else
import std;
#endif

가져온 헤더 파일

일부 헤더는 충분히 자체 포함되므로 키워드를 사용하여 import 가져올 수 있습니다. 가져온 헤더와 가져온 모듈 간의 주요 차이점은 헤더의 전처리기 정의가 문 바로 뒤 import 의 가져오기 프로그램에 표시된다는 것입니다.

import <vector>;
import "myheader.h";

참고하십시오

모듈을 사용하여 C++ 표준 라이브러리 가져오기
module, , importexport
네임드 모듈 튜토리얼
헤더 단위, 모듈 및 미리 컴파일된 헤더 비교