3 ms·
In Rust this is a common pattern because single-element structs are unwrapped by the compiler, but only after typechecking. So they can be easily leveraged to p
by dodobirdlord 5y ago
In Rust this is a common pattern because single-element structs are unwrapped by the compiler, but only after typechecking. So they can be easily leveraged to prevent type confusion between differently typed values with compatible underlying byte representation.
https://doc.rust-lang.org/rust-by-example/generics/new_types.html https://doc.rust-lang.org/rust-by-example/generics/new_types...
So this would look something like:
// single field tuple structs
struct R(u8);
struct G(u8);
struct B(u8);
// using a tuple struct
struct Color(R, G, B);
// or using a struct with named fields
struct Color {
r: R,
g: G,
b: B,
}
I assume something similar can be done in C with no loss of performance under most compilers, since unwrapping a single-field struct is an optimization that a compiler should pick up on every time.
- account42 5y ago> I assume something similar can be done in C with no loss of performance under most compilers, since unwrapping a single-field struct is an optimization that a compiler should pick up on every time. For external functions, it's not an optimization but an ABI requirement (for at least some ABIs) and even for TU-internal functions compilers tend to stick closely to the ABI.
- wizzwizz4 5y agoTrouble is, C doesn't typecheck without pragmas or compiler flags.
- Someone 5y agoYes, that will prevent many errors, but code like this converts bytes to colors, and there, you might accidentally write (example may or may not be valid rust) u8[] a ... Color( a[0], a[1], a[2]) where you should have written Color( a[2], a[1], a[0]) or some other permutation. Also, you’ll need types for every single color space. Do you mean sRGB (https://en.wikipedia.org/wiki/SRGB https://en.wikipedia.org/wiki/SRGB), Adobe RGB (https://en.wikipedia.org/wiki/Adobe_RGB_color_space https://en.wikipedia.org/wiki/Adobe_RGB_color_space), scRGB (https://en.wikipedia.org/wiki/ScRGB https://en.wikipedia.org/wiki/ScRGB), etc. Since that set isn’t fixed (every device potentially had its own RGB gamut) you’ll need a programming language that can create types at run time if you want to write a program that dynamically handles all kinds of devices.
- dodobirdlord 5y agoSomething like this (or the syntactic equivalent) struct R(u8); struct G(u8); struct B(u8); struct Color(R, G, B); u8[] a; ... Color( a[0], a[1], a[2]) wouldn't be valid in Rust. A typedef in C or C++ (or in Rust, which also has them) defines a new name for a type, but it's still type compatible, so you could do something like this. But an 'R' above is not a typedef of u8, it's a separate type, and it is not type compatible. You could not construct a Color by passing a[0] as an argument. You would first have to wrap a[2] as an R, a[1] as a G, a[0] as a B, at which point you would have another opportunity to notice an issue, and you would receive a type error if you tried to call let r: R = R(a[2]); let g: G = G(a[1]); let b: B = B(a[0]); Color(b, g, r); > Also, you’ll need types for every single color space. Do you mean sRGB, Adobe RGB, scRGB, etc. Since that set isn’t fixed (every device potentially had its own RGB gamut) you’ll need a programming language that can create types at run time if you want to write a program that dynamically handles all kinds of devices. Types in Rust don't exist at runtime, they're a compile-time concept, so creating types at runtime doesn't make sense. This sort of thing is generally approached by having the compiler monomorphize generics in places where various representations overlap, and otherwise just having a separate set of types for each non-compatible representation. The correct library would then be picked dynamically from the set of available options compiled into the binary.