C++“error:”object missing in reference to…”取决于gcc版本

4

我在使用gcc 4.3.2版本编译代码时遇到了编译错误,而使用较新的gcc版本(例如4.5.2)则可以编译同样的代码而不会出错。

以下示例说明了这个问题:

class Base {
  protected:
    int member;
};

template<typename T>
class A : public Base {
};

template<typename T>
class C : public A<T> {
    C() {
        Base::member = 1;
    }
};

int main() {
}

在4.3.2版本中,我得到了以下内容:

test.cpp: In constructor 'C<T>::C()':
test.cpp:4: error: object missing in reference to 'Base::member'
test.cpp:14: error: from this location

对于4.5.2版本来说,它可以很好地编译。

如果一个编译器版本接受了代码,那么它就不完全是错误的。我猜测它符合C++标准,但旧的编译器缺乏同样的适当实现。

  1. 问题到底是什么?
  2. 有没有一种可移植的编写方式,让尽可能多的编译器都能接受它?

1
我在4.5版本的发布说明中发现了这个:G++现在实现了DR 176。以前,G++不支持将模板基类的注入类名用作类型名称,并且查找该名称会在封闭范围内找到模板的声明。现在,查找该名称会找到注入类名,该名称可以根据是否跟随模板参数列表而被用作类型或模板。链接到发布说明 - LPs
@LPs 我认为这并不相关,因为Base 不是“模板基类”。编辑:除非它被中介的模板基类所混淆? - Mark B
如果一个编译器版本接受了代码,那么它不可能完全错误。但事实上,C++标准对于何时C++程序无效有相当多的规定。符合要求的C++编译器需要发出诊断(错误/警告/其他消息)。如果编译器没有为无效程序发出错误,则这是编译器中的错误(因此现在您有两个问题:在您的程序和编译器中)。 - Bulletmagnet
@ Mark B:我猜... - LPs
@Bulletmagnet 需要符合规范的C++编译器才能发出诊断(错误/警告/其他消息)。如果编译器对格式不正确的程序没有发出错误,那就是编译器的一个bug...这是否意味着4.5.2比4.3.2更有bug(因为它接受了代码)?对我来说,这更像是在暗示代码不是格式不正确,因为我相信gcc将朝着更好的符合性发展。 - twil
抱歉,我只是在假设。您的代码已被clang(3.7.0)接受,因此很可能是正确的。这意味着GCC 4.5.2比4.3.2更好(至少在这方面是如此 :-))。 - Bulletmagnet
1个回答

2

这绝对是早期版本的g++中的一个bug,但解决方案很简单:只需将表达式中添加 this->,如 this->Base::member = 1;,这会让编译器不再混淆。


我接受这个答案,因为它对我起作用。谢谢!但我仍然不太明白编译器到底在哪里感到困惑。这就像依赖名称一样,也是一个比较棘手的领域。要理解它并不容易,而且你很少会遇到这种情况,以至于很难记住。所以通常情况下,我会在代码中添加一些“typename”,直到编译成功为止... - twil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接