Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I love this technique. It can catch so many errors. It's also easily extensible to slightly more complicated cases. For example, I was working on some gnarly code that was working with a bunch of times with different epochs (e.g. time since startup on the local computer, time since startup on a remote computer, and time since the UNIX epoch). Rather than try to remember what was what, or try to painfully encode it in variable names, I simply wrote a struct that contained the number of seconds and an enum indicating what epoch it used. Then any operation on a pair of times (deltas, comparisons) got factored into a function that asserted the time bases of the two times were compatible.

It's interesting how little use this seems to get in C in general.



That sounds more like a tagged union, which are great for dynamic typing when that's needed, but is a somewhat different technique.


Not at all. It's just a struct with two members:

    struct Time {
        double val;
        enum Epoch epoch;
    };
It works just like one-member structs, in that it can be treated as a single value, passed and returned by value when calling functions, and keeps you from accidentally mixing different kinds of values. Having the "epoch" field along for the ride just means you can add some additional smarts.


So yes, like I was thinking; a tagged union - the epoch field determines the interpretation of the val field. The full application of "wrap values in single element structs for better static guarantees" would be to have a different time struct for every epoch. This is a (possibly quite useful) step back from that, since C's lack of polymorphism would mean a need to implement every time function for epoch even when the logic is the same.


I guess that makes sense now that you explain it. Conceptually, each epoch value results in a different type for the other field, meaning it works like a union, even though it's actually implemented using the same primitive type for each.


Right, exactly. It's just the fact that all inhabitants happen to share a representation that lets you avoid the syntactic union.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: