首先,我的代码在带有编译器的 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
是一个类。
最佳答案
显然 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++ 错误,版本 4.5 及更高版本。那么为什么这应该是合法的呢?
这是 4.5 之前的 g++、clang 和其他编译器中的错误。该标准的相关部分是 3.4.3.1,第 1a 段:
If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition.
换句话说,Obstacle::Obstacle
是非法的,除非用于类 Obstacle
的构造函数的异常定义。
那么这些编译器是如何解析的呢?这些编译器将 Obstacle::Obstacle
视为仅在构造函数的外联定义的情况下具有特殊含义。否则,Obstacle::Obstacle
遵循注入(inject)的名称规则,但忽略该规则不适用于此处的事实。 Obstacle::Obstacle*
不是指向构造函数的指针,因为构造函数没有名称。 Obstacle::Obstacle*
表示从类 Obstacle
的上下文中评估时 Obstacle*
表示的任何内容。但是在类内部,Obstacle*
仍然是指向类 Obstacle
的实例的指针。 Obstacle::Obstacle*
只是一个Obstacle*
,Obstacle::Obstacle::Obstacle*
也是,等等。堆放任意数量的 Obstacle
,它仍然只是一个 Obstacle*
。
关于c++ - std::vector<T> 编译错误 "T cannot appear in a constant-expression",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12883486/