How to automatically convert strongly typed enum into int?

Strongly typed enums aiming to solve multiple problems and not only scoping problem as you mentioned in your question:

  1. Provide type safety, thus eliminating implicit conversion to integer by integral promotion.
  2. Specify underlying types.
  3. Provide strong scoping.

Thus, it is impossible to implicitly convert a strongly typed enum to integers, or even its underlying type - that's the idea. So you have to use static_cast to make conversion explicit.

If your only problem is scoping and you really want to have implicit promotion to integers, then you better off using not strongly typed enum with the scope of the structure it is declared in.


The reason for the absence of implicit conversion (by design) was given in other answers.

I personally use unary operator+ for the conversion from enum classes to their underlying type:

template <typename T>
constexpr auto operator+(T e) noexcept
    -> std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>>
{
    return static_cast<std::underlying_type_t<T>>(e);
}

Which gives quite little "typing overhead":

std::cout << foo(+b::B2) << std::endl;

Where I actually use a macro to create enums and the operator functions in one shot.

#define UNSIGNED_ENUM_CLASS(name, ...) enum class name : unsigned { __VA_ARGS__ };\
inline constexpr unsigned operator+ (name const val) { return static_cast<unsigned>(val); }

A C++14 version of the answer provided by R. Martinho Fernandes would be:

#include <type_traits>

template <typename E>
constexpr auto to_underlying(E e) noexcept
{
    return static_cast<std::underlying_type_t<E>>(e);
}

As with the previous answer, this will work with any kind of enum and underlying type. I have added the noexcept keyword as it will never throw an exception.


Update
This also appears in Effective Modern C++ by Scott Meyers. See item 10 (it is detailed in the final pages of the item within my copy of the book).


A C++23 version would be to use the std::to_underlying function:

#include <utility>

std::cout << std::to_underlying(b::B2) << std::endl;

...or if the underlying type could be a 1 byte type:

std::cout << +(std::to_underlying(b::B2)) << std::endl;

As others have said, you can't have an implicit conversion, and that's by-design.

If you want you can avoid the need to specify the underlying type in the cast.

template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
    return static_cast<typename std::underlying_type<E>::type>(e);
}

std::cout << foo(to_underlying(b::B2)) << std::endl;