enum Color { black, white, red }; // black, white, red are
// in same scope as Color
auto white = false; // error! white already
// declared in this scope
enum class Color { black, white, red }; // black, white, red are scoped to Color
auto white = false; // fine, no other "white" in scope
Color c = white; // error! no enumerator named "white" is in this scope
Color c = Color::white; // fine
auto c = Color::white; // also fine (and in accord with Item 5's advice)
enum class Color { black, white, red }; // enum is now scoped
Color c = Color::red; // as before, but with scope qualifier
if (c < 14.5) { // error! can't compare Color and double
auto factors = // error! can't pass Color to
primeFactors(c); // function expecting std::size_t
if (static_cast<double>(c) < 14.5) { // odd code, but it's valid
auto factors = // suspect, but
primeFactors(static_cast<std::size_t>(c)); // it compiles
…
}
enum class Status; // forward declaration
void continueProcessing(Status s); // use of fwd-declared enum
enum class Status: std::uint32_t; // underlying type for Status is std::uint32_t (from <cstdint>)
enum class Status: std::uint32_t { good = 0,
failed = 1,
incomplete = 100,
corrupt = 200,
audited = 500,
indeterminate = 0xFFFFFFFF
};
Appendix
using UserInfo = // type alias; see Item 9
std::tuple<std::string, // name
std::string, // email
std::size_t> ; // reputation
UserInfo uInfo; // object of tuple type
…
auto val = std::get<1>(uInfo); // get value of field 1
enum UserInfoFields { uiName, uiEmail, uiReputation };
UserInfo uInfo; // as before
…
auto val = std::get<uiEmail>(uInfo); // ah, get value of email field, implicit type conversion
enum class UserInfoFields { uiName, uiEmail, uiReputation };
UserInfo uInfo; // as before
…
auto val =
std::get<static_cast<std::size_t>(UserInfoFields::uiEmail)> // ????
(uInfo);
template<typename E> // C++14
constexpr auto
toUType(E enumerator) noexcept
{
return static_cast<std::underlying_type_t<E>>(enumerator);
}
auto val = std::get<toUType(UserInfoFields::uiEmail)>(uInfo);