|
| 1 | +--- |
| 2 | +description: "Learn more about the /Zc:enumTypes (Enable enum type deduction) compiler option." |
| 3 | +title: "/Zc:enumTypes (Enable enum type deduction)" |
| 4 | +ms.date: 11/07/2022 |
| 5 | +f1_keywords: ["/Zc:enumTypes"] |
| 6 | +helpviewer_keywords: ["-Zc:enumTypes compiler option (C++)", "/Zc:enumTypes compiler option (C++)"] |
| 7 | +--- |
| 8 | +# `/Zc:enumTypes` (Enable enum type deduction) |
| 9 | + |
| 10 | +The **`/Zc:enumTypes`** compiler option enables C++ conforming **`enum`** underlying type and enumerator type deduction. |
| 11 | + |
| 12 | +## Syntax |
| 13 | + |
| 14 | +> **`/Zc:enumTypes`**\[**`-`**] |
| 15 | +
|
| 16 | +## Remarks |
| 17 | + |
| 18 | +The **`/Zc:enumTypes`** compiler option implements Standard C++ conforming behavior for deduction of enumeration base types and the types of enumerators. |
| 19 | + |
| 20 | +The **`/Zc:enumTypes`** option is new in Visual Studio 2022 version 17.4. This option is off by default, and isn't enabled by **`/permissive-`**. To explicitly disable the option, use **`/Zc:enumTypes-`**. |
| 21 | + |
| 22 | +When enabled, the **`/Zc:enumTypes`** option is a potential source and binary breaking change. Some enumeration types change size when the conforming **`/Zc:enumTypes`** option is enabled. Certain Windows SDK headers include such enumeration definitions. |
| 23 | + |
| 24 | +The C++ Standard requires that the underlying type of an enumeration is large enough to hold all enumerators declared in it. Sufficiently large enumerators can set the underlying type of the **`enum`** to **`unsigned int`**, **`long long`**, or **`unsigned long long`**. Previously, such enumeration types always had an underlying type of **`int`** in the Microsoft compiler, regardless of enumerator values. |
| 25 | + |
| 26 | +The C++ Standard also specifies that, within an enumeration definition that has no fixed underlying type, the types of enumerators are determined by their initializers. Or, for the enumerators with no initializer, by the type of the previous enumerator (accounting for overflow). Previously, such enumerators were always given the deduced type of the enumeration, with a placeholder for the underlying type (typically **`int`**). |
| 27 | + |
| 28 | +In versions of Visual Studio before Visual Studio 2022 version 17.4, the C++ compiler didn't correctly determine the underlying type of an unscoped enumeration with no fixed base type. The compiler also didn't correctly model the types of enumerators. It could assume an incorrect type in enumerations without a fixed underlying type before the closing brace of the enumeration. Under **`/Zc:enumTypes`**, the compiler correctly implements the standard behavior. |
| 29 | + |
| 30 | +### Example: Underlying type of unscoped `enum` with no fixed type |
| 31 | + |
| 32 | +```cpp |
| 33 | +enum Unsigned |
| 34 | +{ |
| 35 | + A = 0xFFFFFFFF // Value 'A' does not fit in 'int'. |
| 36 | +}; |
| 37 | + |
| 38 | +// Previously, this static_assert failed. It passes with /Zc:enumTypes. |
| 39 | +static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>); |
| 40 | + |
| 41 | +template <typename T> |
| 42 | +void f(T x) |
| 43 | +{ |
| 44 | +} |
| 45 | + |
| 46 | +int main() |
| 47 | +{ |
| 48 | + // Previously called f<int>, now calls f<unsigned int>. |
| 49 | + f(+A); |
| 50 | +} |
| 51 | + |
| 52 | +// Previously, this enum would have an underlying type of `int`, |
| 53 | +// but Standard C++ requires this to have a 64-bit underlying type. |
| 54 | +// The /Zc:enumTypes option changes the size of this enum from 4 to 8, |
| 55 | +// which could impact binary compatibility with code compiled with an |
| 56 | +// earlier compiler version, or without the switch. |
| 57 | +enum Changed |
| 58 | +{ |
| 59 | + X = -1, |
| 60 | + Y = 0xFFFFFFFF |
| 61 | +}; |
| 62 | +``` |
| 63 | +
|
| 64 | +### Example: Enumerators within an `enum` definition with no fixed underlying type |
| 65 | +
|
| 66 | +```cpp |
| 67 | +enum Enum { |
| 68 | + A = 'A', |
| 69 | + B = sizeof(A) |
| 70 | +}; |
| 71 | +
|
| 72 | +static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes |
| 73 | +``` |
| 74 | + |
| 75 | +In this example the enumerator `A` should have type **`char`** prior to the closing brace of the enumeration, so `B` should be initialized using `sizeof(char)`. Before the **`/Zc:enumTypes`** fix, `A` had enumeration type `Enum` with a deduced underlying type **`int`**, and `B` was initialized using `sizeof(Enum)`, or 4. |
| 76 | + |
| 77 | +### To set this compiler option in Visual Studio |
| 78 | + |
| 79 | +1. Open the project's **Property Pages** dialog box. For details, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md). |
| 80 | + |
| 81 | +1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page. |
| 82 | + |
| 83 | +1. In **Additional options**, add *`/Zc:enumTypes`* or *`/Zc:enumTypes-`*. Choose **OK** or **Apply** to save your changes. |
| 84 | + |
| 85 | +## See also |
| 86 | + |
| 87 | +[`/Zc` (Conformance)](zc-conformance.md)\ |
| 88 | +[`/std` (Specify language standard version)](std-specify-language-standard-version.md) |
0 commit comments