Enum Overview
The enum keyword allows for type-safe enumerated constants to be declared with a specific base type. Enums provide named constants that are grouped together and can be used for type-safe programming where only specific values are valid.
Enum values are distinct from their underlying base type - assigning a raw value of the base type to an enum variable requires an explicit cast<> operation, while enum constants can be freely used where the base type is expected.
Enum Declaration Syntax
[public] enum enum_identifier : base_type {
member_name = value,
[...]
}
- Supported Base Types
- int - integer values
- string - string values
- float - floating-point values
- number - arbitrary-precision numeric values
- Example: Integer Enum
public enum Priority : int {
Low = 0,
Medium = 5,
High = 10,
Critical = 100,
}
Priority p = Priority::High;
printf("Priority value: %d\n", p);
- Example: String Enum
public enum Status : string {
Active = "active",
Inactive = "inactive",
Pending = "pending",
}
Status s = Status::Active;
printf("Status: %s\n", s);
Enum Type Safety
Enums in Qore are strictly typed. While enum values can be used where the base type is expected (for comparison, assignment to base type variables, etc.), the reverse requires an explicit cast.
- Example: Strict Type Enforcement
public enum Color : int {
Red = 1,
Green = 2,
Blue = 3,
}
int i = Color::Red;
int rawValue = 2;
Color c = cast<enum<Color>>(rawValue);
sub processColor(Color c) {
printf("Color value: %d\n", c);
}
processColor(Color::Blue);
processColor(cast<enum<Color>>(3));
Casting to Enum Types
The cast<> operator can be used to convert base type values to enum values. The cast performs runtime validation to ensure the value is a valid enum member.
- Syntax
cast<enum<EnumName>>(expression)
cast<*enum<EnumName>>(expression) - allows NOTHING
- Example: Valid Cast
public enum Status : string {
Active = "active",
Inactive = "inactive",
}
string s = "active";
Status st = cast<enum<Status>>(s);
- Example: Invalid Cast (Runtime Error)
string s = "unknown";
Status st = cast<enum<Status>>(s);
- Example: Wrong Base Type (Runtime Error)
auto v = 123;
Status st = cast<enum<Status>>(v);
- Example: Or-Nothing Cast
*string s;
*Status st = cast<*enum<Status>>(s);
*string s2 = "active";
*Status st2 = cast<*enum<Status>>(s2);
Namespaced Enums
Enums can be declared within namespaces and accessed using the namespace path.
- Example
namespace MyApp {
public enum LogLevel : int {
Debug = 0,
Info = 1,
Warning = 2,
Error = 3,
}
}
MyApp::LogLevel level = MyApp::LogLevel::Warning;
Using Enums in Switch Statements
Enum constants can be used in switch statements for pattern matching.
- Example
public enum Status : string {
Active = "active",
Inactive = "inactive",
Pending = "pending",
}
sub getStatusMessage(Status s) returns string {
switch (s) {
case Status::Active:
return "The item is active";
case Status::Inactive:
return "The item is inactive";
case Status::Pending:
return "The item is pending";
}
}
Enum Reflection
Enums can be inspected at runtime using the reflection module.
- Example
%requires reflection
public enum Priority : int {
Low = 1,
Medium = 2,
High = 3,
}
Enum e = Enum::forName("Priority");
printf("Enum name: %s\n", e.getName());
printf("Base type: %s\n", e.getBaseType().getName());
foreach EnumMember m in (e.getMembers()) {
printf(" %s = %y\n", m.getName(), m.getValue());
}
printf("Is 2 valid? %y\n", e.isValidValue(2));
printf("Is 99 valid? %y\n", e.isValidValue(99));
Direct Enum Type Names
Enum names can be used directly as type names without the enum<...> wrapper. Both syntaxes are equivalent.
- Example
public enum Status : string {
Active = "active",
}
Status s1 = Status::Active;
enum<Status> s2 = Status::Active;
*Status s3;
*enum<Status> s4;
sub process(Status s) { }
sub process2(enum<Status> s) { }
Parse Option Restrictions
Enum declarations can be disabled using the PO_NO_ENUM parse option or the %no-enum parse directive.
- See also
- cast<>
Qore::Reflection::Enum "Enum class"
Qore::Reflection::EnumMember "EnumMember class"