Elektrine lite

← Feed

@erisceleste@tech.lgbt

Post #2813119

2026-05-12 00:01 UTC

@thephd@pony.social if the question is, can you not only match on two types but also introduce identifiers for them, i think you're definitely requiring a tree-like structure of nested generics (outer match on argument 1, each branch of which leads to a match on argument 2, each nbranch of which leads to a match on argument 3 ...) because each introduced identifier would require its own generic, no? i doubt i have much to contribute that you haven't thought of: a few years ago i apparently came up with https://stackoverflow.com/a/25715458/1366431 but i can't see how that's any better than being able to use the function pointer technique now the main thing i was investigating recently was whether you can use generic for open-set/c++ stye overloading: you can, but it's ugly, you just need a dispatcher and to re-register your starting point i don't think this has a ton to do with what it sounds like you want to achieve though sorry @simontatham@hachyderm.io

Replies (1)

  • @simontatham@hachyderm.io 2026-05-12 07:39

    @erisceleste@tech.lgbt @thephd@pony.social unfortunately, nesting Generics brings us back to the original problem, that even the unselected branches have to be semantically valid, so that if you want to accept types (T,T), (T,U), and (U,T), but not (U,U), then you're in trouble, because the sub-Generic in the (U,x) branch which has no case for x=U will fail when you pass types (T,U) to select the other branch. I suppose it's true that if it's feasible to write each branch of the doubly-switched Generic in the form of a function, then you can use the typeof trick to switch between those functions, in the good old-fashioned style of only selecting the function name: inline void foo_ii(int a, int b) { /* ... */ } inline void foo_ip(int a, char *b) { /* ... */ } inline void foo_pi(char *a, int b) { /* ... */ } # define foo(x, y) _Generic( (void (*)(typeof(x), typeof(y)))NULL, void (*)(int, int): foo_ii, void (*)(int, char *): foo_ip, void (*)(char *, int): foo_pi) (x, y) and then you do get both a non-orthogonal set of type pairs, and an identifier for each of the two things at the point of actually using them (in the body of each function).

    Open ##2813120