3

f의 오버로드 위치에서 직관적이지 않은 동작이 발생하는 다음 코드를 고려하십시오. 이 코드는 Clang 3.4.1 및 gcc 4.8에서 경고없이 컴파일됩니다. 템플릿 파라미터에 의존하는 함수 호출에 대한인스턴스화 시점 이후 ADL에서 가장 일치하는 항목을 찾을 수 없습니다. 이 UB인가?

[temp.dep.candidate]

:

template<typename T> 
struct A 
{ 
    static const int value = sizeof(f(T())); 
}; 

struct B 
{ 
}; 

struct D : B 
{ 
}; 

char f(B); 

// instantiates A<D>, unqualified name lookup finds f(B) via ADL 
static_assert(A<D>::value == sizeof(f(B())), ""); // passes 

long f(D); // but wait, f(D) would be a better match! 

// A<D> is already instantiated, f(D) is not found 
static_assert(A<D>::value == sizeof(f(B())), ""); // passes 

는 C++ 11 표준은 상기 코드가 정의되지 않은 동작을 호출 제안 후보 기능은 다음을 제외하고 보통 조회 규칙을 사용하여 찾습니다.

  • 정규화되지 않은 이름 조회 또는 정규화 된 이름 조회는 템플릿 정의 컨텍스트의 함수 선언 만 찾았습니다.
  • 관련 네임 스페이스를 사용하는 조회의 경우 에있는 함수 선언 만 템플릿 정의 컨텍스트 또는 템플릿 인스턴스화 컨텍스트에 있습니다. 함수 이름은 규정 화되지 않은-ID이고 호출이 잘못 형성 될 것이다 또는 더 나은 일치했다 찾아 낼 경우

들에 소개 외부 링크 모든 함수 선언으로 간주 관련 네임 스페이스 내에서 조회 템플릿 정의 및 템플릿 인스턴스화 컨텍스트에있는 선언을 고려하지 않고 모든 번역 단위의 네임 스페이스를 정의하면 프로그램에 정의되지 않은 동작이 발생합니다.

위의 코드는 정의되지 않은 특정 동작을 호출합니까? 고품질 구현을 통해 경고가 표시 될 수 있습니까?

답변

2

위의 코드는 정의되지 않은 특정 동작을 호출합니까?

예. [temp.point]/7

서식 인자에 의존하는 식의 인스턴스화 컨텍스트 인 가진 일련의 선언 외부 링크 선언 템플릿 전문 인스턴스화 지점 이전 동일한 번역 단위.

들어

가 [...]의 특성화는이 [...] 클래스 템플릿 정적 데이터 멤버는 특성화 내재적 인 경우

인스턴스화 점은이 -declaration static_assert 제 직후 인 이 다른 템플릿 전문화 [...] 내에서 참조 되었기 때문에 인스턴스화되었습니다. 그렇지 않으면 이러한 특수화에 대한 인스턴스화 지점은 이 특성화를 참조하는 네임 스페이스 범위 선언 또는 정의 바로 뒤에옵니다.이는 우리가 할 수 없었다 그것이 A<D>::value의 인스턴스의 시점 이후 선언 이후, - 우리가 두 번째 함수 선언을 고려했을 경우

그래서 참으로 좋은 경기가 될 것이다. 인용 한 규칙에 따르면 코드는 정의되지 않은 동작을 유도합니다.
규칙은 기본적으로 템플릿에서 ODR을 종속 이름 조회로 확장합니다.

고품질 구현을 통해 경고가 표시 될 수 있습니까?

아니겠습니까? 또한 정의되지 않은 동작이 컴파일 시간으로 돌아가는 것을 고려하십시오. 컴파일러는 코드가 UB를 유도하면 경고 또는 오류 메시지를 표시 할 수 있지만 필수는 아닙니다. 컴파일러가 항상 불법 코드를 지적하기를 기대하지 마십시오.

+0

'예상'이 너무 강하지 만 경고를받는 것이 바람직합니다. – willj