首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不识别协变量返回类型。

不识别协变量返回类型。
EN

Stack Overflow用户
提问于 2017-06-14 14:56:10
回答 1查看 984关注 0票数 23

出于某种原因,GCC和clang的最新版本都不承认在这种特殊情况下返回类型的协变性。错误信息具有误导性:

代码语言:javascript
复制
error: return type of virtual function 'foo' is not covariant with the return
     type of the function it overrides ('derived *' is not derived from 'base *')

以下是代码:

代码语言:javascript
复制
class base
{
private:
  virtual base * foo() = 0;
};

template< class T >
class foo_default_impl : public virtual base
{
private:
  T * foo() override { return nullptr; }
};

class derived : public virtual base, private foo_default_impl< derived >
{
};

int main() {
  derived d{}; // error: return type of virtual function 'foo' is not covariant with the return type of the function it overrides ('derived *' is not derived from 'base *')
  return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-14 15:35:36

事情是这样的。虽然在我们看来,编译器知道它所需要知道的关于所讨论的类型的一切,但是标准却不这么说。

[tem.arg.type/2]

模板类型参数可能是不完全类型的。- end注意事项 

[basic.type/5]

已声明但未定义的类,特定上下文中的枚举类型(dcl.enum),或未知界限或不完全元素类型的数组,是未完全定义的对象类型.46不完全定义的对象类型,cv是不完全定义的 (basic.fundamental)类型。对象不应定义为不完整类型。

[第2级]

在看到类名之后,就会将类名插入到声明类名的作用域中。类名也被插入到类本身的范围中;这称为注入类名。为了进行访问检查,注入的类名被视为公共成员名。类说明符通常称为类定义.类被认为是在类说明符的结束大括号被看到后被定义的,尽管它的成员函数一般还没有定义。可选属性-说明符-seq属于类;属性-说明符-seq中的属性在命名时被视为类的属性。

粗体的文本描绘出编译器将类型参数T视为不完全对象类型的简单图片。就好像你只转发了声明,就像这样:

代码语言:javascript
复制
class derived;

他们不能推断这个前向声明是从base派生的类。因此,他们不能接受它作为foo_default_impl上下文中的协变返回类型。@marcinj 在评论中指出

[class.virtual.虚拟/8]

如果D​::​f的协变量返回类型中的类类型与B​::​f中的类类型不同,则D​::​f返回类型中的类类型应在D​::​f的声明点完成,或为类D类型。

由于T既不是完整的,也不是foo_default_impl<T>本身,所以它不能是一个协变量返回类型。

票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44548242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档