2017-09-04 12 views
1

나는 이것이 기이하게 반복되는 템플릿 패턴의 예라고 생각한다. 이건 컴파일해야하는 것처럼 보이지만 그렇지 않습니다. 이것은 Xcode 8.3의 Clang과 같습니다. Blarg Fungeable 있기 때문에이 작업을해야처럼왜이 호기심으로 반복되는 템플릿 패턴 예제가 컴파일되지 않습니까?

template<class T> 
class Fungeable 
{ 
public: 
    virtual ~Fungeable() {} 
    virtual bool funge(const Fungeable<T>& inFungeable) const = 0; 
}; 

class Blarg : public Fungeable<Blarg> 
{ 
public: 
    virtual bool funge(const Blarg& inFungeable) const override { return true; } 
}; 

int main(int argc, const char * argv[]) { 
    Blarg b; 
    Blarg x; 
    return static_cast<int>(b.funge(x)); 
} 

는 것 같습니다. 나는이 같은 Fungeable<Blarg>를 취할 Blarg::funge()의 서명을 변경하는 경우 그러나 나는 오류를 'funge' marked 'override' but does not override any member functions

를 얻을 :

class Blarg : public Fungeable<Blarg> 
{ 
public: 
    virtual bool funge(const Fungeable<Blarg>& inFungeable) const override { return true; } 
}; 

그런 다음 그것을 컴파일합니다.

Blarg은 정의로는 Fungeable<Blarg>이므로 첫 번째 버전이 작동하지 않아야합니까?

+1

"Blarg는 정의에 따라 Fungeable "이므로 모든 'Blarg'은 'Fungeable '이지만 'Fungeable '의 모든 것이 'Blarg'는 아닙니다. – tkausl

답변

3

공동 변형 매개 변수 유형은 C++에서 작동하지 않으며 절대로 C++에서 작동하지 않습니다. 당신은 당신의 모범이 "명백하게"안전하다고 생각할 수도 있습니다. 그러나이 기능은 일반적으로 안전하지 않으므로 이러한 작은 사용 사례에 대한 지원을 추가하는 일은 발생하지 않습니다.

는 설명하기 :

struct food {}; 
struct grass : food {}; 

struct animal { 
    virtual void eat(food&) = 0; 
}; 

void feed(animal& a) { 
    a.eat(grass{}); 
} 

를 지금까지 너무 좋아. 이제, 우리 한 공동 변형 매개 변수 유형을 가정의 계층 구조에 더 추가 할 수 있습니다 :

나는 feedlion 개체를 전달할 때 발생하는
struct meat : food {}; 

struct lion : animal { 
    void eat(meat&) {/*...*} 
}; 

? 음식으로는 grass을 처리 할 수 ​​없지만 은 -animal입니다. 이것은 Liskov 치환 원칙을 깨뜨린 것입니다.

+1

첫 번째 문장에서 'return'대신 'parameter'를 의미합니까? –

+0

@MatthewJamesBriggs - 으악. 네 저도 그렇습니다. 공동 변 형 반환 유형이 지원되므로 내 실수가 심각합니다. – StoryTeller