# Enumerations

## Syntax {#syntax}

Enumeration declaration:
> *`enum-decl`* =<br>
> &nbsp;&nbsp;&nbsp;&nbsp;[*`modifier-list`*]<br>
> &nbsp;&nbsp;&nbsp;&nbsp;**`'enum'`** [**`'class'`**] [*`enum-identifier`*]<br>
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[**`':'`** *`tag-type`*]<br>
> &nbsp;&nbsp;&nbsp;&nbsp;**`'{'`** [*`enum-case-decl`* (**`','`** *`enum-case-decl`*)*] **`'}'`**

Enumeration case declaration:
> *`enum-case-decl`* =<br>
> &nbsp;&nbsp;&nbsp;&nbsp;*`enum-const-identifier`* [**`'='`** *`expr`*]

> 📝 **Remark:** The parser currently accepts generic parameters for an enumeration declaration,
> but the parameters are not usable. See GitHub issue
> [#10078](https://github.com/shader-slang/slang/issues/10078) for details.

### Parameters {#parameters}

- *`modifier-list`* is an optional list of modifiers:
  - [\[Flags\]](../../../core-module-reference/attributes/flags-0.html) specifies that the
    enumeration defines flags for a bit field.
  - See also Remark 1 in the Description section below.
- **`'class'`** is a compatibility feature that allows the same enumeration declarations to be shared between
  C/C++ and Slang.
  - See Remark 2 in the Description section below.
- *`enum-identifier`* is the identifier for the declared enumeration type.
  - While the syntax currently allows declaring anonymous enumerations, it is recommended that all
    enumerations be named. See Remark 1 in the Description section below.
- *`tag-type`* specifies the underlying type of the enumeration. If omitted, the default is `int`.
- *`enum-const-identifier`* is an identifier for an enumerator, i.e., an enumerated constant.
- *`expr`* is a [link-time constant](expressions-evaluation-classes.md), specifying the numeric value for the
  enumerator. If omitted, a value is generated by the compiler. See the description below for details.

### Description {#description}

An enumeration is a scalar type that holds a value and may contain named constants, called
*enumerators*. An enumeration has an underlying type that serves as both its storage type and the type of its
enumerators.

The underlying type of an enumeration must be a [Boolean](types-fundamental.md) or an
[integer](types-fundamental.md) type. If no underlying type is specified, the default is `int`.

Enumerations are *scoped*. The named constants of a scoped enumeration are accessed
within the enumeration namespace using the `EnumType.ENUM_CONST` form.

If an enumerator is not assigned a value, one is provided. By default, the value is the previous enumerator's
value incremented by 1. If the value for the first enumerator is unspecified, the default is 0. However, if
[\[Flags\]](../../../core-module-reference/attributes/flags-0.html) is specified for the enumeration, the
provided value is the previous enumerator's value left-shifted by 1, and the default value for the first
enumerator is 1.

Multiple enumerators may share the same numeric value.

An enumeration may be extended using the [extension](types-extension.md#enum) syntax. An extension can be used
to add member functions, constructors, interface conformances, and similar features to the enumeration.


> 📝 **Remark 1:** Slang currently supports *unscoped* enumerations, in which the named constants are defined
> in the same namespace as the enumeration type. The enumerators of an unscoped enumeration can also be
> accessed using the scoped form.
>
> There are three ways to declare an unscoped enumeration:
> - The `slangc` command-line option `-unscoped-enum` makes all named enumerations unscoped, except those
>   that are declared using **`'enum class'`**.
> - The [\[UnscopedEnum\]](../../../core-module-reference/attributes/unscopedenum-08.html) attribute in the
>   modifier list explicitly declares an unscoped enumeration.
> - An anonymous enumeration is unscoped.
>
> However, please note that unscoped enumerations are subject to deprecation and removal, and should therefore
> be avoided in new Slang programs. See GitHub issue
> [#11175](https://github.com/shader-slang/slang/issues/11175) for details.

> 📝 **Remark 2:** Currently, **`'enum class'`** is always a scoped enumeration whereas **`'enum'`** can be
> either scoped or unscoped. If unscoped enumerations are removed from Slang, there will be no difference
> between **`'enum'`** and **`'enum class'`**. New code should prefer **`'enum'`**.



## Examples {#examples}

```hlsl
enum TestEnum
{
    Zero,                    // value 0
    One,                     // value 1
    AnotherOne = One,        // value 1
    Three = One + One + One, // value 3
    Max = 2147483647,
}

RWStructuredBuffer<TestEnum> output1;

[numthreads(1,1,1)]
void main(uint3 threadId : SV_DispatchThreadID)
{
    output1[0] = TestEnum.Zero;       // 0
    output1[1] = TestEnum.One;        // 1
    output1[2] = TestEnum.AnotherOne; // 1
    output1[3] = TestEnum.Three;      // 3
    output1[4] = TestEnum.Max;        // 2147483647
}
```
