C++98 had unscoped enums i.e. -
enum weekdays { mon, tue, wed, thu, fri };
int mon; //Error, mon already used
weekdays a = mon; //Ok
the scope of the enumerators is the scope in which the enum is declared.
C++11 introduces scoped enums i.e. -
enum class weekdays { mon, tue, wed, thu, fri };
int mon; //Ok
weekdays a = mon //Error
weekdays a = weekdays::mon; //Ok
Scoped enums aren't implicitly converted i.e. -
if(a > 3) { } //Error
if(static_cast<int>(a) > 3) { } //Ok
C++11 allows forward declaring both scoped and unscoped enums. For unscoped enums their underlying type needs to be specified and for scoped enums either the default underlying type int is used or can be specified explicitly.
enum weekdays: std::unint32_t;
or
enum class weekdays;
or
enum class weekdays: std::unit32_t;
The underlying type of an enum specifies the number of values that can be enumerated.
Meyers points at a usecase where unscoped enums are useful - when referring to a field within std::tuple -
using userInfo = std::tuple<std::string, std::string, std::size_t>;
userInfo user1;
//....
auto name = std::get<0>(user1); //which field in the tuple is name ?
enum UserInfoFields { Name, Email, Reputation };
auto name = std::get<Name>(user1); //Ok, we know Name is the first field in the tuple
enum weekdays { mon, tue, wed, thu, fri };
int mon; //Error, mon already used
weekdays a = mon; //Ok
the scope of the enumerators is the scope in which the enum is declared.
C++11 introduces scoped enums i.e. -
enum class weekdays { mon, tue, wed, thu, fri };
int mon; //Ok
weekdays a = mon //Error
weekdays a = weekdays::mon; //Ok
Scoped enums aren't implicitly converted i.e. -
if(a > 3) { } //Error
if(static_cast<int>(a) > 3) { } //Ok
C++11 allows forward declaring both scoped and unscoped enums. For unscoped enums their underlying type needs to be specified and for scoped enums either the default underlying type int is used or can be specified explicitly.
enum weekdays: std::unint32_t;
or
enum class weekdays;
or
enum class weekdays: std::unit32_t;
The underlying type of an enum specifies the number of values that can be enumerated.
Meyers points at a usecase where unscoped enums are useful - when referring to a field within std::tuple -
using userInfo = std::tuple<std::string, std::string, std::size_t>;
userInfo user1;
//....
auto name = std::get<0>(user1); //which field in the tuple is name ?
enum UserInfoFields { Name, Email, Reputation };
auto name = std::get<Name>(user1); //Ok, we know Name is the first field in the tuple