/Zc:enumTypes
(启用枚举类型推导)
/Zc:enumTypes
编译器选项支持 C++ 符合性enum
基础类型和枚举器类型推导。
语法
]$
备注
/Zc:enumTypes
编译器选项实现标准 C++ 符合性行为,以推导枚举基类型和枚举器的类型。
/Zc:enumTypes
选项是 Visual Studio 2022 版本 17.4 中的新选项。 此选项默认处于关闭状态,并且/permissive-
未启用该选项。 要显式禁用该选项,请使用/Zc:enumTypes-
。
启用 /Zc:enumTypes
选项后,它是一个潜在的源和二进制中断性变更。 启用符合性/Zc:enumTypes
选项后,一些枚举类型会改变大小。 一些 Windows SDK 标头包括此类枚举定义。
C++ 标准要求枚举的基础类型足够大,足以容纳其中声明的所有枚举器。 足够大的枚举器可以将 enum
的基础类型设置为 unsigned int
、long long
或 unsigned long long
。 以前,这种枚举类型在 Microsoft 编译器中始终具有基础类型int
,无需考虑枚举器的值。
C++ 标准也指定,在没有固定基础类型的枚举定义中,枚举器的类型由其初始值设定项确定。 或者,对于没有初始值设定项的枚举器,由上一个枚举器的类型确定(考虑到溢出)。 以前,此类枚举器始终被赋予枚举的推导类型,带基础类型的占位符(通常为 int
)。
在 Visual Studio 2022 版本 17.4 之前的 Visual Studio 版本中,C++ 编译器未正确确定无固定基类型的未区分范围的枚举的基础类型。 编译器也没有正确为枚举器的类型建模。 如果在枚举的右大括号前面没有固定的基础类型,它可能会在枚举中假定一个不正确的类型。 在/Zc:enumTypes
下,编译器正确实现了标准行为。
示例:无固定类型且未区分范围的enum
的基础类型
enum Unsigned
{
A = 0xFFFFFFFF // Value 'A' does not fit in 'int'.
};
// Previously, this static_assert failed. It passes with /Zc:enumTypes.
static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>);
template <typename T>
void f(T x)
{
}
int main()
{
// Previously called f<int>, now calls f<unsigned int>.
f(+A);
}
// Previously, this enum would have an underlying type of `int`,
// but Standard C++ requires this to have a 64-bit underlying type.
// The /Zc:enumTypes option changes the size of this enum from 4 to 8,
// which could impact binary compatibility with code compiled with an
// earlier compiler version, or without the switch.
enum Changed
{
X = -1,
Y = 0xFFFFFFFF
};
示例:无固定基础类型的enum
定义中的枚举器类型
enum Enum {
A = 'A',
B = sizeof(A)
};
static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes
在此示例中,枚举器 A
的类型 char
应位于枚举的右大括号之前,因此 B
应使用 sizeof(char)
进行初始化。 在 /Zc:enumTypes
修复之前,A
的枚举类型为 Enum
,推导的基本类型为 int
,B
使用 sizeof(Enum)
进行了初始化,或者是 4。
在 Visual Studio 中设置此编译器选项
打开项目的“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
选择“配置属性”>“C/C++”>“命令行”属性页。
在其他选项中添加
/Zc:enumTypes
或/Zc:enumTypes-
。 选择“确定”或“应用”以保存更改。