Last active
March 28, 2016 16:48
-
-
Save mrexodia/2e1d023968ad74f90d85 to your computer and use it in GitHub Desktop.
Variadic templates to solve C-style message callback problems
This file contains 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
#include <stdio.h> | |
#include <stdarg.h> | |
#include <vector> | |
enum Message | |
{ | |
MsgAdd, //int(int, int) | |
MsgNeg, //int(int) | |
MsgRand, //int() | |
}; | |
typedef int Result; | |
typedef int Param; | |
const Param DefaultParam = 0; | |
Result sendMessage(Message msg, int numArgs, ...) | |
{ | |
//get the arguments | |
va_list vaList; | |
va_start(vaList, numArgs); | |
std::vector<Param> params; | |
params.resize(numArgs); | |
for (auto i = 0; i < numArgs;i++) | |
params[i] = va_arg(vaList, Param); | |
va_end(vaList); | |
//TODO: nice implementation for this | |
switch (msg) | |
{ | |
case MsgAdd: | |
{ | |
return params[0] + params[1]; | |
} | |
case MsgNeg: | |
{ | |
return -params[0]; | |
} | |
case MsgRand: | |
{ | |
static auto ran = 0; | |
return ran++; | |
} | |
default: | |
{ | |
return DefaultParam; | |
} | |
} | |
} | |
template<Message M, typename R, typename... P> | |
class Msg | |
{ | |
public: | |
R operator()(P... params) | |
{ | |
return R(sendMessage(M, sizeof...(P), params...)); | |
} | |
}; | |
template<Message M, typename R, typename... P> | |
R MsgCall(P... params) | |
{ | |
return Msg<M, R, P...>()(params...); | |
} | |
typedef Msg<MsgAdd, int, int, int> AddMsg; | |
#define AddFunctionDef(a, b) AddMsg()(a, b) | |
static int AddFunctionInline(int a, int b) { return AddMsg()(a, b); } | |
typedef Msg<MsgNeg, int, int> NegMsg; | |
#define NegFunctionDef(x) NegMsg()(x) | |
static int NegFunctionInline(int x) { return NegMsg()(x); } | |
typedef Msg<MsgRand, int> RandMsg; | |
#define RandFunctionDef() RandMsg()() | |
static int RandFunctionInline() { return RandMsg()(); } | |
//C bindings | |
#define MsgC0(m) sendMessage(m, 0) | |
#define MsgC1(m, p1) sendMessage(m, 1, p1) | |
#define MsgC2(m, p1, p2) sendMessage(m, 2, p1, p2) | |
static int AddFunctionC(int a, int b) | |
{ | |
return MsgC2(MsgAdd, a, b); | |
} | |
static int NegFunctionC(int x) | |
{ | |
return MsgC1(MsgNeg, x); | |
} | |
static int RandFunctionC() | |
{ | |
return MsgC0(MsgRand); | |
} | |
int main() | |
{ | |
auto three = AddMsg()(1, 2); //shows (int, int) with autocompletion | |
three = AddFunctionDef(1, 2); //shows (a, b) with autocompletion | |
three = AddFunctionInline(1, 2); //shows (int a, int b) with autocompletion | |
three = AddFunctionC(1, 2); //shows (int a, int b) with autocompletion | |
auto one = NegMsg()(-1); | |
one = NegFunctionDef(-1); | |
one = NegFunctionInline(-1); | |
one = NegFunctionC(-1); | |
auto ran = RandMsg()(); | |
ran = RandFunctionDef(); | |
ran = RandFunctionInline(); | |
ran = RandFunctionC(); | |
printf("%d %d %d\n", three, one, ran); | |
getchar(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment