True. The same example using repr(union)
:
struct Foo {
kind: FooKind,
data: FooData,
}
enum FooKind {
Ptr,
Num,
}
#[repr(union)]
struct FooData {
ptr: *const u8,
num: u32,
}
fn bar() {
let f: Foo = get_foo();
match (f.kind) {
FooKind::Ptr => ... unsafe { f.data.ptr } ...
FooKind::Num => ... unsafe { f.data.num } ...
}
}
That would look a bit cleaner with anonymous types (allowing f.ptr
).
For that matter, you can pattern match on a struct, so you should be able to
pattern match on a repr(union)
struct, which would look like this:
unsafe {
match (f.kind, f.data) {
(FooKind::Ptr, FooData { ptr }) => ... ptr ...
(FooKind::Num, FooData { num }) => ... num ...
}
}
The match against f.data uses an irrefutable pattern, though if it said
something like num: 42
, that’d be refutable.
So, you can use either pattern matching or field access with repr(union)
structs, too.
(All that said, outside of an example I don’t see any obvious reason to create a DIY tagged union other than matching the layout of one for FFI. If you want a tagged union and you don’t care about its exact layout, enum should work.)