Coming Soon
This lesson is currently being developed
Unscoped enumerator integral conversions
Understand how enums convert to integers.
What to Expect
Comprehensive explanations with practical examples
Interactive coding exercises to practice concepts
Knowledge quiz to test your understanding
Step-by-step guidance for beginners
Development Status
Content is being carefully crafted to provide the best learning experience
Preview
Early Preview Content
This content is still being developed and may change before publication.
13.3 — Unscoped enumerator integral conversions
In this lesson, you'll learn how unscoped enumerations can be converted to and from integers, and the implications of these conversions.
Understanding enumerator values
As you learned in the previous lesson, enumerators are internally represented as integers. This means that enumerations have a close relationship with integral types, and C++ provides ways to convert between them.
Let's start by reviewing how enumerator values work:
#include <iostream>
enum Color
{
red, // 0
green, // 1
blue, // 2
yellow // 3
};
int main()
{
std::cout << "red = " << red << std::endl;
std::cout << "green = " << green << std::endl;
std::cout << "blue = " << blue << std::endl;
std::cout << "yellow = " << yellow << std::endl;
return 0;
}
Output:
red = 0
green = 1
blue = 2
yellow = 3
Implicit conversion from enumeration to integer
Unscoped enumerations can be implicitly converted to integers. This means you can use an enumerator anywhere an integer is expected:
#include <iostream>
enum Priority
{
low = 1,
medium = 5,
high = 10
};
int main()
{
Priority taskPriority = medium;
// Implicit conversion to int
int priorityValue = taskPriority; // No explicit cast needed
std::cout << "Task priority as enum: " << taskPriority << std::endl;
std::cout << "Task priority as int: " << priorityValue << std::endl;
// Can be used in arithmetic operations
int newPriority = taskPriority + 2;
std::cout << "New priority: " << newPriority << std::endl;
return 0;
}
Output:
Task priority as enum: 5
Task priority as int: 5
New priority: 7
Using enumerations in arithmetic operations
Since enumerations convert to integers, you can use them in arithmetic operations:
#include <iostream>
enum Level
{
beginner = 1,
intermediate = 5,
advanced = 10
};
int main()
{
Level currentLevel = intermediate;
Level targetLevel = advanced;
// Calculate difference
int levelDifference = targetLevel - currentLevel;
std::cout << "Levels to advance: " << levelDifference << std::endl;
// Use in comparisons
if (currentLevel < advanced)
{
std::cout << "Still have room to grow!" << std::endl;
}
// Use in calculations
int totalExperience = currentLevel * 100;
std::cout << "Total experience points: " << totalExperience << std::endl;
return 0;
}
Output:
Levels to advance: 5
Still have room to grow!
Total experience points: 500
No implicit conversion from integer to enumeration
While enumerations implicitly convert to integers, the reverse is not true. You cannot implicitly convert an integer to an enumeration:
enum Color
{
red,
green,
blue
};
int main()
{
Color myColor = red; // OK: enumerator to enum
int colorValue = myColor; // OK: enum to int (implicit)
// myColor = 1; // ERROR: can't implicitly convert int to enum
// myColor = colorValue; // ERROR: can't implicitly convert int to enum
return 0;
}
Explicit conversion from integer to enumeration
If you need to convert an integer to an enumeration, you must use an explicit cast:
#include <iostream>
enum Status
{
disconnected = 0,
connecting = 1,
connected = 2
};
int main()
{
int statusCode = 2;
// Explicit conversion using static_cast
Status networkStatus = static_cast<Status>(statusCode);
std::cout << "Status code: " << statusCode << std::endl;
std::cout << "Network status: " << networkStatus << std::endl;
return 0;
}
Output:
Status code: 2
Network status: 2
Dangers of explicit conversion
When explicitly converting integers to enumerations, you need to be careful that the integer value corresponds to a valid enumerator:
#include <iostream>
enum Grade
{
F = 0,
D = 1,
C = 2,
B = 3,
A = 4
};
void printGrade(Grade g)
{
switch (g)
{
case F: std::cout << "Grade: F" << std::endl; break;
case D: std::cout << "Grade: D" << std::endl; break;
case C: std::cout << "Grade: C" << std::endl; break;
case B: std::cout << "Grade: B" << std::endl; break;
case A: std::cout << "Grade: A" << std::endl; break;
default: std::cout << "Invalid grade!" << std::endl; break;
}
}
int main()
{
// Valid conversions
Grade grade1 = static_cast<Grade>(2); // C
Grade grade2 = static_cast<Grade>(4); // A
printGrade(grade1);
printGrade(grade2);
// Dangerous conversion - invalid enumerator value!
Grade invalidGrade = static_cast<Grade>(99);
printGrade(invalidGrade); // Undefined behavior!
return 0;
}
Output:
Grade: C
Grade: A
Invalid grade!
Working with user input
A common use case for integer-to-enumeration conversion is when processing user input:
#include <iostream>
enum MenuChoice
{
newGame = 1,
loadGame = 2,
settings = 3,
quit = 4
};
void handleChoice(MenuChoice choice)
{
switch (choice)
{
case newGame:
std::cout << "Starting new game..." << std::endl;
break;
case loadGame:
std::cout << "Loading saved game..." << std::endl;
break;
case settings:
std::cout << "Opening settings..." << std::endl;
break;
case quit:
std::cout << "Goodbye!" << std::endl;
break;
}
}
bool isValidChoice(int choice)
{
return choice >= 1 && choice <= 4;
}
int main()
{
int userInput;
std::cout << "Main Menu:" << std::endl;
std::cout << "1. New Game" << std::endl;
std::cout << "2. Load Game" << std::endl;
std::cout << "3. Settings" << std::endl;
std::cout << "4. Quit" << std::endl;
std::cout << "Enter choice: ";
std::cin >> userInput;
if (isValidChoice(userInput))
{
MenuChoice choice = static_cast<MenuChoice>(userInput);
handleChoice(choice);
}
else
{
std::cout << "Invalid choice!" << std::endl;
}
return 0;
}
Example Output (with input "2"):
Main Menu:
1. New Game
2. Load Game
3. Settings
4. Quit
Enter choice: Loading saved game...
Enumerations in function parameters
You can pass enumerations to functions that expect integers:
#include <iostream>
enum ErrorCode
{
success = 0,
fileNotFound = 404,
accessDenied = 403,
serverError = 500
};
void logError(int code)
{
std::cout << "Error code: " << code << std::endl;
}
int calculateSeverity(int code)
{
if (code == 0) return 0; // No error
if (code < 500) return 1; // Client error
return 2; // Server error
}
int main()
{
ErrorCode error = fileNotFound;
// Can pass enum to function expecting int
logError(error); // Implicit conversion
int severity = calculateSeverity(error);
std::cout << "Error severity level: " << severity << std::endl;
return 0;
}
Output:
Error code: 404
Error severity level: 1
Best practices for enumeration conversions
1. Avoid mixing enumerations and integers in arithmetic
enum Size
{
small = 1,
medium = 5,
large = 10
};
int main()
{
Size shirtSize = medium;
// Questionable: mixing enum with magic number
int newSize = shirtSize + 3; // What does +3 mean?
// Better: use meaningful enum values
if (shirtSize == small)
{
shirtSize = medium; // Explicit upgrade
}
return 0;
}
2. Validate integer inputs before converting to enum
#include <iostream>
enum Priority
{
low = 1,
medium = 2,
high = 3
};
bool isValidPriority(int value)
{
return value >= 1 && value <= 3;
}
int main()
{
int input = 5; // Invalid priority
if (isValidPriority(input))
{
Priority p = static_cast<Priority>(input);
// Use p safely
}
else
{
std::cout << "Invalid priority value!" << std::endl;
}
return 0;
}
Output:
Invalid priority value!
3. Consider using explicit underlying types
You can specify the underlying integer type for an enumeration:
#include <iostream>
enum Status : char // Explicitly use char as underlying type
{
inactive = 'I',
active = 'A',
pending = 'P'
};
int main()
{
Status currentStatus = active;
char statusChar = currentStatus; // Implicit conversion to char
std::cout << "Status character: " << statusChar << std::endl;
return 0;
}
Output:
Status character: A
Key concepts to remember
-
Unscoped enumerations implicitly convert to integers - no cast required.
-
Integers do not implicitly convert to enumerations - explicit cast required.
-
Use static_cast for integer-to-enumeration conversion and validate the input.
-
Enumerations can be used in arithmetic operations because they convert to integers.
-
Always validate integer values before converting to avoid undefined behavior.
-
You can specify the underlying type of an enumeration explicitly.
Summary
Unscoped enumerations have a close relationship with integers. They can be implicitly converted to integers, allowing them to be used in arithmetic operations and comparisons. However, converting integers back to enumerations requires explicit casting and careful validation to ensure the integer represents a valid enumerator value. Understanding these conversion rules is essential for safe and effective use of enumerations in your programs.
Quiz
- Can you implicitly convert an enumeration to an integer? What about the reverse?
- What happens if you use static_cast to convert an invalid integer to an enumeration?
- Why might you want to validate integer inputs before converting them to enumerations?
- How can you specify the underlying type of an enumeration?
- What are the potential dangers of using enumerations in arithmetic operations?
Practice exercises
Try these exercises to practice enumeration conversions:
- Create an enumeration for months (1-12) and write a function that takes an integer and safely converts it to the month enumeration.
- Create an enumeration for HTTP status codes and write a function that categorizes them (1xx info, 2xx success, etc.) using arithmetic operations.
- Write a program that reads integers from the user and converts them to a day-of-week enumeration, with proper validation.
- Create an enumeration with explicit char values and demonstrate conversion between the enum and character representation.
Explore More Courses
Discover other available courses while this lesson is being prepared.
Browse CoursesLesson Discussion
Share your thoughts and questions