I need to store type-erased pointers, and I've been using pointers to u8
s, but I was curious whether or not there's a reason to use a raw pointer to a ()
instead. I think I've seen that before in a couple cases.
I kind of like the meaning that NonNull<()>
implies, compared to NonNull<u8>
which looks like it might intentionally point to a u8
while NonNull<()>
seems to indicate it's pointing to something that you don't know what it is.
either is ok IMO because you typically keep the implementation private, and raw pointer always need unsafe
to convert back, you just need to pay attention to those unsafe usages. if however you expose it in public APIs, I'd suggest use some custom opaque type (maybe uninhabited) instead:
pub enum Void {}
type Erased = NonNull<Void>;
or use the void
crate.
1 Like
Oh, I like uninhabited idea, but I just found a page in the 'nomicon that said it was bad for FFI. I just found the c_void
type in the standard library, and I'm wondering if that makes sense to use. I've got a couple functions in my API that I might want to be able to be implemented externally at some point so that might be a reason to use that instead.
well, I thought you were talking about rust only. if it's for ffi, then c_void
is just for that. a pointer to c_void
is equivalent to it's C counterpart. i.e. *const c_void
=> void const *
and *mut c_void
=> void *
. NonNull<c_void>
is roughly the same as * mut c_void
, but C doesn't have an equivalent "non-null" concept.
The RawWakerVTable
API in the standard library uses *const ()
.
1 Like
Yeah, I hadn't thought about it until you mentioned void, and then I found the c_void
, so I'll use that for now. Thanks!