c++ 横向协变:return 类型因类型不完整而不同

c++ crosswise covariant: return type differs due to incomplete type

我正在试验协方差,并提出了以下示例,该示例至少不能使用 clang 11 和 VS2015 进行编译:

class Number {
public:
    virtual ~Number () = default;
    virtual Number const * increment()const = 0;
};

class Even;

class Odd : public Number {
public:
    // error: increment() is not covariant because Even is incomplete
    Even const * increment()const; 
};

class Even : public Number {
public:
    Odd const * increment()const;
};

它与 有关但不是重复的,因为两个被覆盖的函数中的常量是相同的。

标准支持吗?

是否有解决此问题的方法或任何实现类似行为的建议?

您可以使用 non-virtual 界面实现类似的功能(尽管它有更多的行并且看起来更容易搞砸):

class Number {
public:
    virtual ~Number() = default;
    Number const * increment() const { return do_increment(); }
private:
    virtual Number const * do_increment() const = 0;
};

class Even;

class Odd : public Number {
public:
    Even const * increment() const;
private:
    Number const * do_increment() const override;
};

class Even : public Number {
public:
    Odd const * increment() const { return do_increment(); }
private:
    Odd const * do_increment() const override;
};

inline Even const * Odd::increment() const {
    return static_cast<Even const *>(do_increment());
}

虽然您尝试实现的目标可能有解决方法,但显示的代码无效。

根据class.virtual#9

If the class type in the covariant return type of D​::​f differs from that of B​::​f, the class type in the return type of D​::​f shall be complete at the point of declaration of D​::​f or shall be the class type D. ...

链接文本中有此规则的示例。

在您的情况下,由于 Odd::increment 的 return 类型不是 Number,并且 Even 在声明 Odd::increment 时不完整,代码是 ill-formed.

我在这个错误的答案中找到了答案,因此 deleted answer 由 @Brian 撰写以回应您链接到的问题。