I do and have done this. Like I said, it’s not often I need constructors, but when you are working with large structs, or polymorphic ones, they can make life easier.
Odin’s zero-initialization is great, and I do make the zero value meaningful, but sometimes you want defaults that aren’t zero while still being able to override other fields. No need to “litter” the codebase with constructors if default struct member initialization was possible.
BlendMode :: enum {
Opaque,
Alpha,
Additive,
}
PipelineDesc :: struct {
depth_test: bool,
blend_mode: BlendMode,
sample_count: i32,
line_width: f32,
// ... many more members
}
create_pipeline_desc :: proc(
depth_test: bool = true,
blend_mode: BlendMode = .Opaque,
sample_count: i32 = 1,
line_width: f32 = 1.0,
// ...
) -> PipelineDesc {
return {
depth_test,
blend_mode,
sample_count,
line_width,
// ...
}
}
main :: proc() {
pipeline := create_pipeline_desc(blend_mode = .Alpha)
}
With default struct member initialization, you could imagine something like the following. Essentially the same code in main, but you can check the struct definition to understand the defaults immediately. No need to find a constructor in the codebase. If you are using a library, you might not even know the constructor exists:
PipelineDesc :: struct {
depth_test: bool = true,
blend_mode: BlendMode = .Opaque,
sample_count: i32 = 1,
line_width: f32 = 1.0,
// ...
}
main :: proc() {
pipeline := PipelineDesc{blend_mode = .Alpha}
}