tu_local — 변환 유닛 로컬 개체
tu_local — 변환 유닛 로컬 개체 (Translation-unit-local entities)
변환 유닛 로컬(TU-local) 개체는 로컬로 간주되는 개체(다른 변환 유닛에서 사용되지 않음)가 다른 변환 유닛에 노출되어 사용되는 것을 막기 위해 도입됐어요. 즉, 모듈을 쓸 때 내부 구현이 외부로 새는 것을 방지하는 규칙이에요.
모듈 기능에서 내부 연결을 가진 개체를 외부에 노출하면, 그 개체의 정의가 "내부적이지 않게" 되어 모듈 경계를 넘어 사용될 위험이 생겨요. TU-local 규칙은 이런 위험을 막아줘요.
출처: cppreference
본문
변환 유닛 로컬(TU-local) 개체는 로컬로 간주되는 개체(다른 변환 유닛에서 사용되지 않음)가 다른 변환 유닛에 노출되어 사용되는 것을 막기 위해 도입됐어요.
예를 들어, import Foo; 한 뒤에 어떤 모듈에서 반환된 타입이 내부 타입이라면, 그 타입의 정의가 더 이상 내부적이지 않게 되어 모듈 외부에서 사용될 수 있는 문제가 생겨요. TU-local 규칙은 이런 상황을 컴파일 오류로 처리해요.
TU-local 개체
어떤 개체가 TU-local이 되려면 다음 중 하나여야 해요.
- 다음 중 하나인 타입, 함수, 변수, 또는 템플릿
- 내부 연결(internal linkage)을 가진 이름을 가지거나,
- 연결을 가진 이름이 없고, TU-local 개체의 정의 안에서 선언되거나 람다 표현식으로 도입된 경우
- 클래스 지정자, 함수 본문, 또는 초기화자 밖에서 정의된 이름 없는 타입이거나, TU-local 개체만 선언하는 데 쓰이는 정의 타입 지정자로 도입된 경우
- TU-local 템플릿의 특수화
- 어떤 TU-local 템플릿 인자를 가진 템플릿의 특수화
- (가능하면 인스턴스화된) 선언이 노출(exposure)인 템플릿의 특수화
어떤 값이나 객체가 TU-local이 되려면 다음 중 하나예요.
- TU-local 함수이거나 TU-local 변수와 연관된 객체이거나 그에 대한 포인터, 또는
- 클래스 또는 배열 타입의 객체이고, 그 부분 객체나 참조 타입의 비정적 데이터 멤버가 가리키는 객체/함수 중 하나가 TU-local이면서 상수 표현식에서 사용 가능한 경우
노출 (Exposure)
선언이 다음 중 하나라면 **노출(exposure)**이에요 — TU-local 개체를 이름 짓는 경우 (단, 다음은 무시):
- 비인라인 함수나 함수 템플릿의 함수 본문
- 변수나 변수 템플릿의 초기화자 (변수의 타입은 제외)
- 클래스 정의 안의 friend 선언
- 내부 또는 무연결을 가진 비휘발성 const 객체/참조에 대한 참조 중 상수 표현식으로 초기화되고 ODR-사용이 아닌 것
또는 TU-local 값으로 초기화된 constexpr 변수를 정의하는 경우.
TU-local 제약 (TU-local constraints)
모듈 인터페이스 유닛(비공개 모듈 프래그먼트 밖) 또는 모듈 파티션에서, 비-TU-local 개체의 (가능하면 인스턴스화된) 선언이 노출이면 프로그램은 잘못된 형식이에요. 다른 맥락에서 그런 선언은 deprecated예요.
한 변환 유닛에 나타난 선언이 다른 변환 유닛에서 선언된 TU-local 개체를 이름 짓는데 그 변환 유닛이 헤더 유닛이 아니면, 프로그램은 잘못된 형식이에요.
예제 (Example)
변환 유닛 #1:
module A;
void other()
{
g<0>(); // OK: 특수화가 명시적으로 인스턴스화됨
g<1>(); // 오류: 인스턴스화가 TU-local its 를 사용
h(N::A{}); // 오류: 오버로드 집합에 TU-local N::adl(int) 포함
h(0); // OK: adl(double) 호출
adl(N::A{}); // OK; N::adl(int) 는 찾지 못하고, N::adl(N::A) 호출
fr(); // OK: f 호출
constexpr auto ptr = fr; // 오류: fr 은 여기서 상수 표현식에 사용 불가
}
모듈 안에서 TU-local 개체를 사용하는 특수화나 오버로드가 오류가 되는 모습을 보여줘요. 같은 모듈이라도 내부 연결을 가진 개체를 인터페이스가 노출하는 것을 컴파일러가 막아주는 거예요.