Guide
Defining an enum
The members are listed after the type name, either on one line or in a begin block. A member without a value gets the value of the previous member plus one, and the first member starts at zero.
julia> @cenum Fruit apple=1 orange=2 kiwi=2
julia> @cenum Day begin
Mon = 1
Tue
Wed
end
julia> Tue
Tue::Day = 2Each member becomes a constant in the module where @cenum is called. A value can be any expression that evaluates to an integer when the macro is expanded, such as 1 << 4 or a constant defined earlier in the module.
Several members may share a value. They are then the same object, which is shown under the first of its names:
julia> orange === kiwi
true
julia> kiwi
orange::Fruit = 2Base type
The integer type used to store the enum can be given after the name. It has to be a primitive integer type.
julia> @cenum Color::UInt8 red green blue=0x10
julia> sizeof(Color)
1
julia> Integer(blue)
0x10Without one, the base type is Int32, which is what C compilers use for most enums. If a value does not fit in an Int32, the first of UInt32, Int64 and UInt64 that can hold all the values is used instead:
julia> @cenum Mask small=20 large=5123123123
julia> typeof(Integer(large))
Int64When a C header is translated, give the base type the C compiler chose, so that the size of the enum matches in ccall and in struct layouts.
Values without a name
As in C, an enum can hold any value of its base type. Converting an integer never fails as long as it fits the base type:
julia> Fruit(2)
orange::Fruit = 2
julia> Fruit(7)
Fruit(7)This is what makes enums usable as bit flags, see below.
Operators
Members can be compared with integers and with members of other enums. The comparison is made on the underlying values.
julia> apple == 1
true
julia> apple < orange
true
julia> apple in Set([1, 2])
true+, -, *, ÷, &, |, xor, ~, << and >> work between members and integers. They return an integer, not an enum; wrap the result in the type to get an enum back.
julia> @cenum Flags::UInt32 readable=1 writable=2 executable=4
julia> readable | writable
0x00000003
julia> Flags(readable | writable)
Flags(0x00000003)
julia> (Flags(0x03) & writable) != 0
true
julia> apple + 1
2Conversion and ccall
Integer(x) gives the underlying value in the base type, and any integer type can be used as a constructor in the same way.
julia> Integer(orange)
2
julia> UInt8(orange)
0x02A @cenum type is a primitive type with the size of its base type, so it can be used directly as an argument or return type in ccall, and as a field type in structs that mirror C structs. An enum value can also be passed where the C function expects the underlying integer type.
ccall((:set_color, libfoo), Cvoid, (Color,), green)
ccall((:get_color, libfoo), Color, ())read(io, T) and write(io, x) read and write the underlying integer.
Names and members
julia> instances(Fruit)
(apple, orange, orange)
julia> Symbol(apple)
:apple
julia> string(orange)
"orange"
julia> typemin(Day), typemax(Day)
(Mon, Wed)instances has one entry for each name, so a value with several names appears more than once. Symbol and string give the first name of a value, and :UnknownMember if it has none.
Displaying the type lists its members:
julia> Fruit
Cenum Fruit:
apple = 1
orange = 2
kiwi = 2Dispatching on enums
All types defined with @cenum are subtypes of CEnum.Cenum, which is parameterized by the base type. It is not exported.
julia> Fruit <: CEnum.Cenum{Int32}
true
julia> describe(x::CEnum.Cenum) = string(typeof(x), " with value ", Integer(x));
julia> describe(apple)
"Fruit with value 1"