모듈 인터페이스에서 인라인 의미


24

헤더 파일을 고려하십시오.

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept : ID(ID_) {}

  int GetID() const noexcept { return ID; }
};

또는 대안 적으로 :

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept;

  int GetID() const noexcept;
};

inline T::T(int const ID_) noexcept : ID(ID_) {}

inline int T::GetID() const noexcept { return ID; }

사전 모듈 환경에서 이러한 헤더는 ODR 위반없이 여러 TU에 텍스트로 포함될 수 있습니다. 또한 관련 멤버 함수가 비교적 작기 때문에 컴파일러는 해당 함수를 "인라인"(사용할 때 함수 호출을 피함)하거나 일부 인스턴스를 T모두 최적화 할 수 있습니다 .

C ++ 20이 끝난 회의에 대한 최근 보고서 에서 다음 진술을 읽을 수 있습니다.

우리는 inline모듈 인터페이스에서 의 의미를 명확하게 설명했다 : 의도적으로 선언 inline되지 않은 함수 본문은 해당 함수 본문이 모듈 인터페이스에 나타나는 경우에도 모듈의 ABI에 속하지 않는다. 모듈 작성자에게 ABI를보다 강력하게 제어 할 수 있도록 모듈 인터페이스의 클래스 본문에 정의 된 멤버 함수는 더 이상 암시 적으로 적용되지 않습니다 inline.

내가 실수하지 않았는지 모르겠습니다. 모듈 세계에서 컴파일러가 함수 호출을 최적화 할 수 있으려면 inline클래스 내에서 정의 된 것처럼 주석을 달아야 합니까?

그렇다면 다음 모듈 인터페이스가 위의 헤더와 동일합니까?

export module M;

export
class T
{
private:
  int const ID;

public:
  inline explicit T(int const ID_) noexcept : ID(ID_) {}

  inline int GetID() const noexcept { return ID; }
};

여전히 모듈을 지원하는 컴파일러가 없지만 inline향후 리팩토링을 최소화하기 위해 적절한 경우 그렇게 사용하고 싶습니다.

답변:


11

모듈 세계에서 컴파일러가 함수 호출을 최적화 할 수 있으려면 inline클래스 내에서 정의 된 것처럼 주석을 달아야 합니까?

어느 정도까지.

인라인은 "있는 것처럼"최적화되며 컴파일러가 영리한 경우 번역 단위 간에도 인라인이 발생할 수 있습니다.

즉, 단일 번역 단위 내에서 작업 할 때 인라인이 가장 쉽습니다. 따라서, 쉬운 인라인을 촉진하기 위해, inline선언 된 함수는 사용되는 모든 번역 단위에서 정의를 제공해야합니다. 이것은 컴파일러가 확실히 인라인 할 것 (또는 inline정규화 되지 않은 함수를 인라인하지 않을 것)을 의미하지는 않지만 인라인이 TU 내에서보다는 TU 내에서 발생하기 때문에 인라인 프로세스에서 훨씬 쉽게 일을 수행합니다.

사전 모듈 세계에서 클래스 내에 정의 된 클래스 멤버 정의는 inline암시 적 으로 선언 됩니다. 왜? 정의가 클래스 내에 있기 때문입니다. 사전 모듈 세계에서 TU간에 공유되는 클래스 정의는 텍스트 포함으로 공유됩니다. 따라서 클래스에 정의 된 멤버는 해당 TU간에 공유되는 헤더에 정의됩니다. 따라서 여러 TU가 동일한 클래스를 사용하는 경우 해당 여러 TU는 클래스 정의와 헤더에 선언 된 멤버의 정의를 포함하여 그렇게합니다.

즉, 당신은 어쨌든 정의를 포함하고 있습니다 inline.

물론 이것은 함수의 정의가 이제 클래스 텍스트의 일부라는 것을 의미합니다. 헤더에 선언 된 멤버의 정의를 변경하면 해당 헤더를 포함하는 모든 파일을 재귀 적으로 재 컴파일합니다. 클래스의 인터페이스 자체가 변경되지 않더라도 다시 컴파일해야합니다. 따라서 그러한 기능을 암시 적으로 만드는 inline것은 이것을 변경하지 않으므로 그렇게 할 수도 있습니다.

사전 모듈 환경에서이를 피하기 위해 C ++ 파일에서 멤버를 정의하면 다른 파일에 포함되지 않습니다. 쉽게 인라이닝을 잃지 만 컴파일 타임을 얻습니다.

그러나 여기에있는 것이 있습니다 : 이것은 수업을 여러 장소에 전달하기위한 수단으로 텍스트 포함을 사용하는 결과입니다.

모듈 식 세계에서는 Java, C #, Python 등과 같은 다른 언어에서 볼 수 있듯이 클래스 자체에서 각 멤버 함수를 정의하려고 할 수 있습니다. 이렇게하면 코드 지역성이 합리적으로 유지되고 동일한 함수 서명을 다시 입력하지 않아도되므로 DRY의 요구에 부응 할 수 있습니다.

그러나 모든 멤버가 클래스 정의 내에 정의되어 있으면 이전 규칙에 따라 해당 멤버가 모두 inline됩니다. 그리고 모듈이 함수를 허용하게 inline하려면 이진 모듈 아티팩트에 해당 함수의 정의가 포함되어야합니다. 이는 그러한 함수 정의에서 한 줄의 코드조차도 변경할 때마다 모듈에 따라 모든 모듈과 함께 재귀 적으로 모듈을 빌드해야 함을 의미합니다.

암시 적 inline모듈을 제거 하면 정의를 클래스 외부로 이동하지 않고도 텍스트 포함 일과 동일한 기능을 사용할 수 있습니다. 어떤 함수 정의가 모듈의 일부이고 어떤 함수 정의가 아닌지 선택할 수 있습니다.


8

이것은 며칠 전에 프라하에서 채택 된 P1779 에서 나온 것 입니다. 제안에서 :

이 백서에서는 (명명 된) 모듈에 첨부 된 클래스 정의에 정의 된 함수에서 암시 적 인라인 상태를 제거 할 것을 제안합니다. 이를 통해 클래스는 중복 선언을 피함으로써 인라인 유무에 관계없이 함수를 선언 할 때 모듈 작성자에게 제공되는 유연성을 유지할 수 있습니다. 또한 클래스 템플릿의 삽입 된 친구 (일반적으로 클래스 정의 외부에서 정의 할 수 없음)가 인라인이 아닌 것을 허용합니다. 또한 NB 주석 US90을 해결합니다 .

종이는 (다른 것들 중에서) 문장을 제거했습니다.

클래스 정의 내에 정의 된 함수는 인라인 함수입니다.

그리고 문장을 추가했습니다 :

전역 모듈에서 클래스 정의 내에 정의 된 함수는 암시 적으로 인라인됩니다 ([class.mfct], [class.friend]).


귀하의 예 export module M는 초기 프로그램과 동등한 모듈입니다. 컴파일러는 이미 주석 처리되지 않은 인라인 함수를 수행한다는 점에 유의하십시오 . 추론에 키워드 inline의 존재를 추가로 사용하는 것 inline입니다.


따라서 inline키워드가없는 모듈의 함수 는 컴파일러에 의해 인라인되지 않습니다. 맞습니까?
metalfox

1
@metalfox 아니요, 맞습니다.
Barry

1
내가 참조. 감사. cpp 파일에 정의 된 것과 같으며, 반드시 링크 타임에 인라인 될 필요는 없습니다.
metalfox
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.