-
Structs .
-
Default values are not allowed.
Structs with Parametric Polymorphism (Parapoly)
Table_Slot :: struct($Key, $Value: typeid) {
occupied: bool,
hash: u32,
key: Key,
value: Value,
}
slot: Table_Slot(string, int)
-
Example :
-
Odin-handle-map with
$HT: typeid:-
Caio:
-
I have a question about the odin-handle-map :
Handle_Map :: struct($T: typeid, $HT: typeid, $N: int) { // Each item must have a field `handle` of type `HT`. items: [N]T, num_items: u32, next_unused: u32, unused_items: [N]u32, num_unused: u32, }-
I don't understand the use of
$HT: typeid, theHTis not used inside this struct, so why is it there? Does it have the same influence from outside the struct?
-
-
Thag:
-
It's because it allows other procs to then infer the handle type based on the type of the map
-
i.e.
remove :: proc(m: ^Handle_Map($T, $HT), h: HT) -
notice how
HTcan be known from the type specified in the handle map definition
-
-
Caio:
-
so it's just type information for the handle it holds? I mean, if I were to make a
distincthandle?
-
-
Thag:
-
you're right, it's type info that is then used by other procs at compile time.
-
-
Chamberlain:
-
I've done something similar with my Vulkan abstraction, haha. Good to see someone else used poly this way too.
-
-
-
Subtype Polymorphism (Keyword
using
)
-
When using
usingon structs , this gives subtyping (inheritance). -
"It's like
embeddingin Go, but a little more explicit". -
Technically it is possible to "force" OOP via the use of "function tables" ("V tables", virtual tables) and using
usingto simulate inheritance:-
-
"just function pointers with a fancy name".
-
-
-
Using
usingin other places:-
In procedures :
-
Ginger Bill: "It was a mistake".
-
Teej: "I can see this being useful when using RayLib a lot inside a function and I just want to drop the
rl.". -
Ginger Bill: "I still think that's bad, don't use it. It's just 3 characters, it's not worth it".
-
Ginger Bill: "I regret adding this as a feature, because it only leads to unreadable spaghetti code. Try not to use it, this is a mistake.".
-
-
In file scopes:-
Not possible.
-
Ginger Bill: "I disallowed using
usingat the file scope, because it makes it harder to understand where the code is coming from".
-
-
Struct Memory Layout
#packed
-
Removes padding between fields that is normally inserted to ensure all fields meet their type’s alignment requirements.
-
The fields remain in source order.
-
Useful where the structure is unlikely to be correctly aligned (the insertion rules assume it is ), or if space savings are more important than access speed.
-
Accessing a field in a packed struct may require copying the field out into a temporary location, or using a machine instruction that doesn’t assume the pointer is correctly aligned, to be performant or avoid crashes on some systems. (See
intrinsics.unaligned_load.)
struct #packed {...}
#aligned(N)
-
Specifies that the struct will be aligned to
Nbytes. -
This applies to the struct itself, not its fields.
-
Fields remain in source order.
-
Can also be applied to a union .
struct #align(4) {...}
#raw_union
-
Struct’s fields will share the same memory space, similar to
unions in C. -
All fields share the same offset (
0). -
Useful especially for bindings.
struct #raw_union {...}
Equivalence
-
Arrays :
Vec3 :: [3]f32 Vec3 :: struct { x: f32, y: f32, z: f32, } -
Matrices
Matrix4x4 :: #row_major matrix[4, 4]f32 Matrix4x4 :: struct { m11, m12, m13, m14: f32, m21, m22, m23, m24: f32, m31, m32, m33, m34: f32, m41, m42, m43, m44: f32, }
Reflect
Struct
Struct Fields
-
Type_Info :: struct { size: int, align: int, flags: Type_Info_Flags, id: typeid, variant: union { // etc }, } -
reflect.struct_field_value_by_name(any, string, bool) -> any. -
-
Represents information of a struct field
Struct_Field :: struct { name: string, type: ^runtime.Type_Info, tag: Struct_Tag, offset: uintptr, // in bytes is_using: bool, }-
reflect.struct_fields_zipped(typeid) -> soa array Struct_Field.-
Returns the fields of a struct type
Tas an#soaslice. -
Useful for iteration.
-
-
reflect.struct_field_by_name(typeid, string) -> Struct_Field. -
reflect.struct_field_value(any, Struct_Field) -> any.field := struct_field_value_by_name(the_struct, "field_name") value_by_field := struct_field_value(the_struct, field)
-
-
-
Represents the
stringtype of a struct field. -
By convention, tags are concatenations of optionally space-separated key:"value" pairs. Each key is non-empty and contains no control characters other than space, quotes, and colon.
Struct_Tag :: distinct string-
reflect.struct_tag_lookup(Struct_Tag, string) -> (string, bool).-
Returns the value associated with a key in the tag string.
-
-
reflect.struct_tag_get(Struct_Tag, string) -> string.-
Wrapper around
struct_tag_lookupignoring theokvalue.
-
-
Other tags
#no_copy
-
This tag can be applied to a
structto forbid copies. The initialization of a#no_copytype must be implicitly zero, a constant literal, or a return value from a call expression.
Mutex :: struct #no_copy {
state: uintptr,
}
main :: proc() {
m: Mutex
v1 := m // This line will raise an error.
p := &m
v2 := p^ // So will this line.
}