m0n*_*awk -1 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;
}
Run Code Online (Sandbox Code Playgroud)
我有一段代码可以通过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
Run Code Online (Sandbox Code Playgroud)
这段代码出了什么问题?
你的代码是正确的.很明显,因为警告只是一个警告.它指的是这种比较涉及两个不相关的枚举,因此可能不合理.
如果您对分析感兴趣:
因为您正在为x86-32进行编译,sizeof(void*)所以是4.所以a<>引用a<4>,然后a<4>::b引用一个枚举器.
所以表达式声明
a<>::b<c>d;
Run Code Online (Sandbox Code Playgroud)
被解析为
(a<>::b < c) > d;
Run Code Online (Sandbox Code Playgroud)
现在执行通常的算术转换,在此期间int使用整数提升规则将两个操作数提升.[expr.rel]/2:
通常的算术转换是在算术或枚举类型的操作数上执行的.[...].转换后,操作数应具有相同的类型.
(注意粗体部分,稍后会确保.)[expr]/10:
此模式称为通常的算术转换,其定义如下:
- 如果任一操作数具有作用域枚举类型(7.2),则不执行任何转换; 如果另一个操作数的类型不同,则表达式格式不正确.
- [......关于浮点类型的子弹点...]
- 否则,应对两个操作数执行整体促销(4.5).然后,以下规则应适用于提升的操作数:
- 如果两个操作数具有相同的类型,则不需要进一步转换.
- [...]
[conv.prom]/3涵盖了普查员的整体推广:
其基础类型未固定的无范围枚举类型的prvalue(7.2)可以转换为以下第一种类型的prvalue,它们可以表示枚举的所有值(即b min到b范围内的值)最大为7.2所述): ,
int,unsigned int,long int,unsigned long int,long long int或unsigned long long int.
在两个操作数被提升之后int,表达式的结果是false(因为0不小于0).
然后比较这个促销的结果d- 这里,如上所述d被提升int,而比较的结果 - 类型bool- 也被提升int.[conv.prom]/6:
类型的prvalue
bool可以转换为类型的prvalueint,false变为零并true成为一个.
所以两个操作数都有类型int.第二个外部比较产生true,因为false- > 0小于1,值d.