함수 템플릿이 반환 유형을 추론 한 경우 정의를 인스턴스화하지 않고 호출하는 방법이 있습니까?
다음과 같은 일부 기능 템플릿을 고려하십시오.
template <class T>
const auto& foo() { static T t; return t; }
경우 정의는 유효하지 않을 T
수 있었다 void
. 그럼에도 불구하고 오류를 유발하지 않고 선언 만 인스턴스화 할 수 있습니다 .
extern template const auto& foo<void>(); // explicit instantiation declaration
이제 foo
명시 적으로 인스턴스화되지 않고 호출 되는 상황을 고려해 보겠습니다 . 분명히 foo
평가 된 컨텍스트에서를 호출하면 전문화의 정의가 인스턴스화됩니다. 평가되지 않은 상황에서는 어떻습니까? 추론되지 않은 반환 유형을 가진 함수 템플릿이 평가되지 않은 컨텍스트에서 호출되면 전문화의 정의가 인스턴스화되지 않는다는 것을 알고 있습니다. 이것의 명백한 예는 std::declval<T>
. 추론 된 반환 유형을 가진 함수에 대해 동일한 것이 가능한지 여부는 명확하지 않습니다.
예를 들어, 나는 이것을 고려했습니다.
static_assert(sizeof( (void)foo<void>(), char{} ) == 1);
그러나 컴파일러가 sizeof
반환 유형을 모르고 표현식 을 평가하기에 충분한 정보를 확실히 가지고있는이 상황에서도 여전히 컴파일 오류가 발생합니다 ( godbolt link ).
foo<void>
이 상황에서 정의의 인스턴스화를 요구하는 표준 조항은 무엇입니까 ?foo<void>
정의를 인스턴스화하지 않는 평가되지 않은 표현식 내부에서 호출 할 수 있는 방법이 있습니까?
답변
foo<void>
이 상황에서 정의의 인스턴스화를 요구하는 표준 조항은 무엇입니까 ?
비 규범이기는하지만에 메모 [dcl.spec.auto] / 11 한다는 것을 언급 어떤 (선언 된 반환 형식의 자리 표시 자와 함수 템플릿의) 전문성의 사용이 암시 적 인스턴스화의 원인이됩니다 [추출물, 강조 광산] :
[...] [ 참고 : 따라서 함수 템플릿 의 특수화 를 사용 하면 암시 적 인스턴스화가 발생합니다.
또한 [dcl.spec.auto] / 14 는 인스턴스화를 트리거하지 않고 명시 적 인스턴스화 선언을 허용하는 특정 사례를 다루며, 함수 템플릿의 반환 유형을 결정하기 위해 트리거 된 인스턴스화 메커니즘이 다음과 다소 분리되어 있음을 암시하기도합니다. "일반적인"인스턴스화 메커니즘 [ 강조 내] :
명시 적 인스턴스화 선언은 자리 표시 자 유형을 사용하여 선언 된 엔티티의 인스턴스화를 유발 하지 않지만 해당 엔티티가 유형을 결정하는 데 필요한대로 인스턴스화되는 것을 방지하지 않습니다 . [ 예 :
template <typename T> auto f(T t) { return t; } extern template auto f(int); // does not instantiate f<int> int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit // instantiation definition is still required somewhere in the program
— 최종 예 ]
여기에서 예제에 대한 주석 (비 규범 적)은 그러한 특수한 경우 트리거 된 암시 적 인스턴스화가 반환 유형 추론에만 사용되며 다른 곳에서 명시 적 인스턴스화 정의에 대한 필요성을 포기하지 않는다고 지적합니다.
foo<void>
정의를 인스턴스화하지 않는 평가되지 않은 표현식 내부에서 호출 할 수 있는 방법이 있습니까?
위의 논의를 감안할 때 아니오라고 말할 것입니다. 평가되지 않은 표현 내에서도 호출은 (비 규범 적) "모든 사용"에 속합니다.