std :: vector <t>编译错误“T不能出现在常量表达式”</t>

时间:2012-10-14 15:12:44

标签: c++ g++ llvm

首先,我的代码在带有编译器的Mac OS X上编译并运行正常

i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1

但是在Ubuntu上有编译器

g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

它不会编译。

在我的标题中我有

std::vector<Obstacle::Obstacle*> obstacles;

在Ubuntu中给出以下编译错误:

error: ‘Obstacle::Obstacle’ cannot appear in a constant-expression

我需要改变什么才能让它发挥作用? 我是否应该在Ubuntu上使用一些神奇的编译标志,使其在OS X上工作?

谢谢

编辑:Obstacle是一个班级。

2 个答案:

答案 0 :(得分:4)

显然Obstacle只是一个班级。

令人惊讶的是,以下内容也适用于g ++ 4.2,g ++ 4.3,g ++ 4.4,clang ++ 2.9和clang ++ 3.1:

std::vector<Obstacle::Obstacle::Obstacle::Obstacle::Obstacle*> obstacles;

g ++的多个版本和clang的多个版本编译了上述内容。

g ++ 4.5和4.6有这个结构的问题。这看起来像g ++ bug,版本4.5及更高版本。那为什么这是合法的呢?

这是4.5 g ++,clang以及其他编译器之前的错误。该标准的相关部分是3.4.3.1,第1a段:

  

如果嵌套名称说明符指定了一个类C,并且在嵌套名称说明符之后指定的名称(在C中查找时)是C的注入类名(第9节),则名称为而是考虑命名类C的构造函数。这样的构造函数名称只能在出现在类定义之外的构造函数定义的declarator-id中使用。

换句话说,Obstacle::Obstacle是非法的,除非在类Obstacle的构造函数的行外定义中使用。

那么这些编译器如何解析呢?这些编译器仅将Obstacle::Obstacle视为具有特殊含义,仅适用于构造函数的异常定义。否则,Obstacle::Obstacle遵循注入的名称规则,但忽略该规则不适用于此的事实。 Obstacle::Obstacle*不是指向构造函数的指针,因为构造函数没有名称。相反,Obstacle::Obstacle*表示在Obstacle*类的上下文中进行评估时Obstacle的含义。但是在类中,Obstacle*仍然是指向类Obstacle的实例的指针。 Obstacle::Obstacle*只是Obstacle*Obstacle::Obstacle::Obstacle*也是如此,依此类推。堆积尽可能多的Obstacle s,它仍然只是Obstacle*

答案 1 :(得分:1)

您不能将构造函数指针作为存储类型传递。

而不是

std::vector<Obstacle::Obstacle*> obstacles;

std::vector<Obstacle*> obstacles;