Last active
August 29, 2015 14:07
-
-
Save mkmik/05e027f75460251d992a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Quick and dirty optional option struct via function overload via preprocessor trick. | |
* | |
* requires C99 and gnu extension, for ", ## __VA_ARGS" | |
*/ | |
#include <stdio.h> | |
///////// Magic library | |
// expand to prefix + suffix where suffix is either s0 or s0 depending whether the vararg list is the same length as | |
// args or 1 item longer. | |
// usage: #define function M_DISPATCH(function, _one, _two, M_FIXED_ARGS(arg0, arg1), ## __VA_ARGS__) | |
#define M_DISPATCH(prefix, s0, s1, args, ...) M_CONCAT(prefix, VA_SUFFIX(s0, s1, 0, ## __VA_ARGS__))(args, ## __VA_ARGS__) | |
// call it to declare the list of the fixed arguments of the function | |
#define M_FIXED_ARGS(...) __VA_ARGS__ | |
// returns either a or b depending of whether it's called by 1 or 2 vararg arguments | |
// note: not zero, you have pass a dummy first argument for it to work if you want to | |
// discriminate between 0 or 1 parameters. | |
#define __BAD _ARG_LIST_TOO_LONG_RTFM | |
#define VA_SUFFIX(a,b,...) VA_SUFFIX_IMPL(__VA_ARGS__, __BAD, __BAD, __BAD, b, a) | |
#define VA_SUFFIX_IMPL(_1,_2,_3,_4,_5, N,...) N | |
// double indirection needed to concatenate two macro expansions | |
#define M_CONCAT(x,y) M_PASTER(x,y) | |
#define M_PASTER(x,y) x ## y | |
////////// REAL CODE | |
// ---- ns_send | |
typedef struct { | |
int deadline; | |
int n_headers; | |
} ns_send_opts_t; | |
// define a dispatcher that will invoke ns_send_legacy if invoked with only two parameters | |
// and ns_send_opts if invoked with three parameters. | |
#define ns_send(addr, body, ...) M_DISPATCH(ns_send, _legacy, _opts, M_FIXED_ARGS(addr, body), ## __VA_ARGS__) | |
void ns_send_opts(char* addr, char* body, ns_send_opts_t opts) { | |
printf("sending %s to %s, deadline: %d, headers: %d\n", addr, body, opts.deadline, opts.n_headers); | |
} | |
void ns_send_legacy(char* addr, char* body) { | |
ns_send_opts(addr, body, (ns_send_opts_t){0}); | |
} | |
////////// USAGE | |
int main() { | |
ns_send("x", "addr"); | |
ns_send_opts_t opts = {.deadline = 1}; | |
ns_send("x", "addr", opts); | |
// not super nice, but parseable error message indicating that there are too many arguments | |
// ns_send("x", "addr", opts, x); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment