Structural Typing in C!!! Finally done hammering on this damn thing. Fuck.
https://thephd.dev/_vendor/future_cxx/papers/C%20-%20_Record%20types.html
Fuck!!
Structural Typing in C!!! Finally done hammering on this damn thing. Fuck.
https://thephd.dev/_vendor/future_cxx/papers/C%20-%20_Record%20types.html
Fuck!!
@thephd besides working with existing code, the one-sided compatibility can also be a tool for type safety, e.g.:
struct _Record vec3 { float x,y,z; };
struct vec3_direction { float x,y,z; };
struct vec3_position { float x,y,z; };
e.g. all these are vec3, but, vec3_direction and vec3_position are not interchangeable (without first converting to vec3).
I guess it's similar to how, for example, int* and float* are both considered void* if needed, but int* and float* are not interchangeable.
@thephd Ooh, this sounds very neat.
I think there may be a slight error with the canonical link for the page though. It seems to go to a different page about _Operators.
@thephd Questioning the bit about _Record being entirely meaningless on forward declarations. If I have a function that takes a bla_vec3 *, I would expect to be able to pass a foo_vec3 * to it if they are compatible record types. But if I can't declare that fact on forward-declarations, I gotta go dig out the full type definitions just to get the _Record modifier.
That's okay, it's structural typing after all so I'm gonna need to provide the structure, but the error message I get from the compiler would be Less Than Awesome. It's just gonna tell me those types are incompatible and then I have to intuit that my include soup is missing a secret ingredient.
Allowing _Record on there would at least let the compiler give a clear hint in its diagnostic that hey this is a structural type but you didn't include the structure.
@MinkOfTheEnd I don't want people to think that adding _Record on a forward declaration is enough to make something a record, because it's fundamentally impossible for that to work. I think that's a greater danger than the missed include, which will be more obvious when doing any operation on a forward-declared type.
That being said, if implementations or vendors can coalesce on [[vendor::record(foo_vec, bar_vec, bla_vec)]] as a way to mark forward declarations for compatibility / record-ness, maybe that would be a more worthwhile endeavor so we don't have to leave it up to implementations to guess / provide a much stronger error.
@thephd Some thoughts from the maintainer of a small C implementation:
1. I think structural typing in C would be valuable.
@sheumann I don't really have any connotation for "extending a base type with more members" because that's just inheritance to my brain. You could make a version of composition where you can add a member to a structure and then give it a way to say "actually, all of my members are part of the thing you put me inside". That might give you the layout of composition but the "feel" of extension/inheritance that you're looking for.
When I write "anonymous" in my prose, I'm just referring to structures and unions without tags. The official standardese is very clear that we are not modifying the base algorithm: however you were comparing bitfields before, and however you were comparing anonymous unions/structures before, you keep doing that just with the strcmp for the names removed for _Record(types). For just _Record, the tag name at the top level is ignored, but everything else proceeds as normal.
I don't think I want regular attribute syntax, due to attributes being ignorable. This cannot be ignorable: it changes the way code is written, and changes a fundamental property (compatibility rules). I wouldn't mind discarding _Record(types) and _Record(vendor::stuff) to just keep the base one, though it should be known that doing so will cook usecases.
I'm glad you think structural typing is valuable! Hopefully we can make progress with something along the lines of _Record.
@thephd That looks very interesting, thanks - as always - for your hard work!
One minor point of copy-editing: the final comment in the second code sample of par. 3.7 probably needs to be updated - presumably, the point of vendor::const is to _allow_ that code?
Again, thanks! Good to see C getting all sorts of neat goodies / 21st century features!