为什么这段代码不适用于 -m32?
Why this code didn't work for -m32?
#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
此代码怎么了?
您的代码正确。显然,由于警告只是警告。它指出了以下事实:比较涉及两个无关的枚举,因此也许不明智。
如果您对分析感兴趣:
由于您要编译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)。然后,以下规则应适用于 促进操作数:
- 如果两个操作数具有相同的类型,则不需要进一步的转换。
- […]
枚举者的积分促销涵盖了[Cons.Prom]/3:
一种未涉及的枚举类型的贵族,其基础类型不是 固定(7.2)可以转换为第一个的贵族 以下可以表示枚举的所有值的类型 (即,范围 b min to 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
,而比较结果 - bool
型的结果也促进了int
。[cons.prom]/6:
bool
类型的prvalue可以转换为int
类型false
变为零,true
成为一个。
因此,这两个操作数具有int
类型。第二个,外部比较得出true
,因为false
-> 0
小于1
,即d
的值。
您的代码是没有错误的编译,实际错误在链接时发生。运行时库的链接器很可能无法找到 32位版本。您是否在系统上安装了它们?
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 为什么 std::erase(std::erase_if) 不是适用于<algorithm>任何容器的模板?
- 为什么这适用于 G++ 而不是 CLANG?
- 为什么不区分大小写适用于 std::unordered_set的 std::hash 函数?
- 声明适用于 auto,但不能显式声明类型?
- 什么是通用运行时组件 #ifdef 适用于Windows(UWP)而不是iOS
- Windows 上的 Cmake 不添加共享库路径(适用于 linux)
- Typedef适用于结构,但不适用于枚举,仅适用于C++
- 为什么函数模板不理解 NULL,但适用于 nullptr
- 链接器读取库,但在其中找不到符号?未解析的外部符号,但仅适用于 Win32 而不是 x64
- Netbeans 8.1(适用于 C/C++)找不到我的编译器(gcc-6.0.0 开发版本)
- random_shuffle() 适用于 Windows,但不能在 Linux 上编译
- C++指针到方法模板推导在面向 x86 时不编译,但适用于 x64
- 不在异常中嵌入std::字符串的规则是否仍然适用于move构造函数
- 移动文件夹Windows c++:适用于Vista及以上版本,不包括XP
- 适用于Android的Qt找不到任何兼容的设备答案找到但不知道如何
- 在Windows 7上不起作用,但它适用于Windows 8 dll。
- 可变参数模板转换为 std::function<R(ARGS...)>适用于 GCC 而不是 MSVC2013,为什么?
- C++11 cmath 函数不在 std 命名空间中,适用于 android NDK w/gcc-4.8 或 clang