Skip to content

Instantly share code, notes, and snippets.

@mrexodia
Last active March 28, 2016 16:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrexodia/2e1d023968ad74f90d85 to your computer and use it in GitHub Desktop.
Save mrexodia/2e1d023968ad74f90d85 to your computer and use it in GitHub Desktop.
Variadic templates to solve C-style message callback problems
#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