2016-07-22 4 views
16

이 코드는 g ++ 6.1에서 성공적으로 컴파일하지만, 그 소리 3.8 오류를 제공합니다공변 반환 형식, CONST 네스, 불완전한 클래스

class C; 

class Base { 
public: 
    virtual const C *getC(); 
}; 

class Derived : public Base { 
public: 
    virtual  C *getC(); 
}; 

는 다음과 연타에서 오류가 될 때 :

$ dev/compilers/linux-x86_64-2.12.2/clang3.8/bin/clang++ -Wall -c testcovariantreturn.cxx 
testcovariantreturn.cxx:10:20: error: return type of virtual function 'getC' is not covariant with the return type of the function it overrides ('C' is incomplete) 

클래스 C가 전달 선언보다 완전히 정의 된 경우 오류가 없습니다. 내 이해는 가상 메서드를 재정의 할 때 공변 (covariant)이 "적은"cv-qualification (즉, 반환 유형에서 const 삭제)을 허용한다는 것입니다.

완전한 형식을 요구하는 clang이 올바른지/허용 되었습니까? 그렇다면 이유는 무엇입니까? C의 정의를 어떻게 사용할 수 있습니까?

이것은 완전히 학문적 인 것이 아니며 큰 코드베이스에서 불필요한 포함을 추가하기를 꺼려하며 표준 사례로 선언하려고합니다.

+0

이 코드는 공변이므로 이상적으로 받아 들여야합니다. 반대의'const' 분산은 공변 적이 지 않을 것이며 원래'const' 객체의 UB 수정을 지원할 것입니다. C++ 표준이 무엇에 관해서 말하고 있는지는 모르겠다. –

답변

17

이것은 clang 3.8 버그입니다. 특히 26297입니다. N4594에서 [class.virtual, 표현에서 :

최우선 함수의 리턴 타입의 함수의 클래스가 오버라이드 (override) 기능 또는 공변의 반환형 동일이어야한다. 함수 이 함수 B::f을 무시한 경우 함수의 반환 유형 은 다음 조건을 만족하면 공 변합니다. (7.1) - 둘 다 클래스에 대한 포인터이거나 둘 다 클래스에 대한 왼쪽 값 참조이거나 둘 다 에 대한 참조입니다 클래스
(7.2) - 반환 유형이 B::f 인 클래스는 반환 유형이 D::f 인 클래스와 동일하거나 반환 유형이 D::f 인 클래스의 모호하지 않고 액세스 할 수있는 직접 또는 간접 기본 클래스 입니다.
(7.3) - 포인터 또는 참조가 모두 동일한 cv- 자격을 가지고 반환 유형의 클래스 유형이 D::f 인 경우 리턴 유형이 B::f 인 클래스 유형과 동일한 cv-qualification을 갖습니다.

B::f 반환 C const*D::f 반환 C* 일치 이러한 요구 사항을 모두 (어느 포인터가 이력서 - 자격 및 D::f의 클래스 유형이 적은 이력서 자격을 갖춘베이스보다) 갖는, 따라서이를 허용해야한다.

완전성에 대한 요구 사항은 없습니다. C은 이러한 기준을 확인하기 위해 완료 할 필요가 없습니다.

+0

오, 나는 당신이 논평하기 전에 대답을 읽었어야했다. 그래서 표준이 말하는 것 또한 알았습니다. Upvoted. :) –

+0

자세한 문구가 시간이 지남에 따라 변경되는 경향이 있으므로 어떤 표준 또는 초안을 인용했는지 말씀해주십시오. 감사. –

+0

@ Cheersandhth.-Alf 물론입니다. 이 부분은 실제로 변경되지 않았습니다. 2005 년 초안의 문구는 기본적으로 동일합니다 (rvalue reference에 대한 modulo 단어). – Barry

3

나는 또한 당신의 코드에 문제가없는 것을 발견했다. 그것은 3.8 버전과 그 이전 버전을 제외하고, 시도한 모든 컴파일러와 clang의 헤드 버전으로 컴파일됩니다.

Live demo

관련 표준 텍스트 :

10.3 노트 8 :

D :: F의 공변 반환 형식의 클래스 유형이 으로부터 B의 다른 경우 :: f의 클래스 유형의 반환 유형 D :: f는 이며은 D :: f 또는 클래스 타입이어야한다 D.

클래스 유형 완전 동일하거나 이어야합니다 공변 방법,하지만 난 그것을 이해 CONST/휘발성 차이가 여전히 같은 클래스로 간주됩니다 예를 들어 합법적으로 만들려면을 입력하십시오.

+0

'const'차이는 공분산에 영향을줍니다. override가 pointee에'const'를 추가하면, 타입 시스템 (캐스트 없음) 내에서 원래'const' 오브젝트에 대한 포인터를 리턴 할 수 있습니다. 그런 다음 기본 클래스 가상 함수를 사용하는 클라이언트 코드 코드는 원래 'const' 개체 인 = UB를 수정하려고 시도 할 수 있습니다. –

+0

C++ 표준 지원에 대해서는 잘 모르겠지만 표준의 표현과는 상관없이 대단히 중요합니다. :) –

+0

@ Cheersandhth.-Alf, 그렇습니다. 그러나 제가 언급하고자했던 것은 구체적으로 불완전한 타입이 허용 될 때를 말합니다. –

관련 문제