为什么这段代码对-m32不起作用?

时间:2015-05-07 17:47:57

标签: c++ templates g++ 32bit-64bit

#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

此代码有什么问题?

2 个答案:

答案 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)所述:   intunsigned intlong intunsigned long intlong 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小于01的值。

答案 1 :(得分:-1)

您编写的代码没有错误,链接时会发生实际错误。很可能链接器无法找到运行时库的 32位版本。你有没有在你的系统上安装它们?