#include <stddef.h>
template<size_t N = sizeof(void*)> struct a;
template<> struct a<4> {
enum { b };
};
template<> struct a<8> {
template<int> struct b {};
};
enum { c, d };
int main() {
a<>::b<c>d;
d;
}
我有一段代码可以通过gcc成功编译x64架构。但是-m32
出现错误时失败了:
$ g++ -m32 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:16:12: warning: comparison between ‘enum a<4u>::<anonymous>’ and ‘enum<anonymous>’ [-Wenum-compare]
a<>::b<c>d;
^
collect2: error: ld returned 1 exit status
此代码有什么问题?
答案 0 :(得分:8)
您的代码是正确的。很明显,因为警告只是一个警告。它指的是这种比较涉及两个不相关的枚举,所以也许并不合理。
如果您对分析感兴趣:
由于您正在为x86-32进行编译,sizeof(void*)
为4.因此a<>
引用a<4>
,随后a<4>::b
引用枚举数。
所以表达式语句
a<>::b<c>d;
被解析为
(a<>::b < c) > d;
现在执行通常的算术转换,在此期间,使用整数提升规则将两个操作数提升为int
。 [expr.rel] / 2:
通常的算术转换是在操作数上执行的 算术或枚举类型。 [...]。 转换后,操作数应具有相同的类型。
(注意粗体部分,稍后会确保。)[expr] / 10:
此模式称为通常的算术转换, 其定义如下:
- 如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果其他操作数不相同 类型,表达形式不正确。
- [...有关浮点类型的要点......]
- 否则,应在两个操作数上执行整体促销(4.5)。然后,以下规则适用于 推广操作数:
- 如果两个操作数具有相同的类型,则无需进一步转换。
- [...]
[conv.prom] / 3:
涵盖了普查员的整体推广未编组的枚举类型的prvalue,其基础类型不是 fixed(7.2)可以转换为第一个的prvalue 以下类型可以表示枚举的所有值 (即 b min 到 b max 范围内的值,如7.2)所述:
int
,unsigned int
,long int
,unsigned long int
,long long int
或unsigned long long int
。
将两个操作数提升为int
后,表达式的结果为false
(因为0
不小于0
)。
然后将此促销的结果与d
进行比较 - 此处,d
如上所述被提升为int
,而比较的结果 - 类型为{{ 1}} - 也被提升为bool
。 [conv.prom] / 6:
int
类型的prvalue可以转换为bool
类型的prvalue,int
变为零,false
成为一个。
因此两个操作数都具有类型true
。第二个外部比较产生int
,因为true
- &gt; false
小于0
,1
的值。
答案 1 :(得分:-1)
您编写的代码没有错误,链接时会发生实际错误。很可能链接器无法找到运行时库的 32位版本。你有没有在你的系统上安装它们?