2017-09-04 9 views
1

これは、不思議な繰り返しテンプレートパターンの例だと思います。これはコンパイルするべきだと私は思うが、そうはしない。これはXcode 8.3のClangにあります。なぜこの不思議な繰り返しのテンプレートパターンの例はコンパイルされませんか?

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)); 
} 

Blarg Fungeableあるので、これは動作するはずのように思えます。私はこのような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++で動作しません。あなたの事例は「明らかに」安全だ​​と考えるかもしれません。しかし、この機能は一般的に安全ではなく、このような小さなユースケースのサポートを追加することはできません。

は説明するために:

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

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

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

をこれまでのところは良いです。

struct meat : food {}; 

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

私はfeedlionオブジェクトを渡すとき、何が起こる:今、私たちは共同変パラメータの型を持っていると仮定すると、階層に多くを追加してみましょうか?食品としてgrassは処理できませんが、は-animalです。これはリスコフ置換原理を破る。

+1

最初の文章では、「返品」ではなく「パラメータ」を意味しますか? –

+0

@MatthewJamesBriggs - うん。ええ、やりますよ。共変種の戻り値の型がサポートされています。 – StoryTeller

関連する問題