为什么这个奇怪的重复出现的模板模式示例没有编译?

时间:2017-09-04 05:22:18

标签: c++ templates compiler-errors crtp

我相信这是一个奇怪的重复模板模式的例子。在我看来,这应该编译,但事实并非如此。这与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。但我收到错误'funge' marked 'override' but does not override any member functions

如果我将Blarg::funge()的签名更改为Fungeable<Blarg>,请执行以下操作:

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

然后编译。

根据定义,Blarg的{​​{1}}是不是第一个版本的工作?

1 个答案:

答案 0 :(得分: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&) {/*...*}
};

lion对象传递给feed时会发生什么?它无法处理grass作为食物,但它是一个 animal。这打破了利斯科夫的替代原则。