void dothing(const dothingArgs& args);
...
dothing({ .arg1 = 1, .arg2 = someOtherThing });
Register colouring should make it run the same as regular args for the most part in optimized builds.
This has two benefits:
1) Changing the order of the struct args won't introduce ordering bugs like with function signatures.
2) Default arguments are more explicit and there's less chance of breakage as the argument list grows over time and gets more default values, as tends to happen.
And 2 drawbacks:
1) Passing complex types as arguments without copying can be tricky.
2) The compiler errors don't tell you specifically which arguments are broken, at least in g++. This one sucks the most imo.