Written by on August 13, 2023 in C++, Programming with 0 Comments

The type trait “std::is_scoped_enum<T>::value” was introduced in C++23 to check whether the type “T” is a scoped enum type. Another way to use this is std::is_scoped_enum_v<T>.

Before getting into this trait in detail, let us briefly recap the differences between unscoped and scoped enums.

Unscoped Enums

Unscoped enums are the old-style enums. Look at the following example:

Unscoped Enums

Unscoped Enums

The enum keyword is usually followed by a name (optional) followed by a list of symbols within braces. Line 11 is a special case where the underlying type of the enum elements is explicitly stated. When this is not given, the compiler is free to choose any underlying integral type.

The above example shows that such enums are unsafe because of implicit conversion to integral type. Also note that the enum elements are visible at the scope where the enums are defined, and there is no need to use the scope resolution operator to access them. This can easily lead to problems later on.

Here is the output from the program:

Program Output

Program Output

Unscoped enums are not recommended in newer programs.

Scoped Enums

Scoped enums were introduced in C++11. In contrast to unstopped enums, these enums are type safe without implicit conversion to the underlying type. The following example illustrates this:

Scoped Enums

Scoped Enums

The key difference is the use of the keyword class or struct as part of the enum definition. Although either of them can be used with the same effect, the preferred convention is to use class.

Note that we need to use explicit type casting to convert the enum elements to the underlying integral type. In addition, we have to use the scope resolution operator to access the members.

If we uncomment lines 39 – 41, the program won’t compile!


Now we return to our type trait is_scoped_enum<T>::value, where “T” is a type name. Its abbreviated form is is_scoped_enum_v<T>. This returns “true” if “T” happens to be a scoped enum, else it returns “false”. Here is an example:

is_scoped_enum_v<T> Example

is_scoped_enum_v Example

The corresponding output is:

Program Output

Program Output

As expected, the trait correctly differentiates between scoped enums and other types.

OK, how do we use this feature in a program? One usage scenario is to take advantage of C++23 “Concepts” to define constraints on function argument types. The following example shows how to do this:

Constraining Function Argument

Constraining Function Argument

The “foo()” function is defined to accept argument of any scoped enum type by constraining the type. That way, the compiler can easily differentiate between valid and valid argument types, especially with template functions.

The example C++ program can be downloaded here. I used Visual Studio Professional 2022 Ver 17.6.5 to build this program.

Have a nice weekend!


Tags: ,


If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published. Required fields are marked *