Indeed this could work out, but I'm waiting my laptop to arrive, and just of curiosity I have tried to drag mcserver compatibility back to vs2012.
Apparently I've managed to compile the code, however I have made quit serious cracks in code, so I suspect I've managed to brake it down - because it now claims about stack overflow exception, meanwhile according to call stack it did not reach deeply enough. I probably need to debug bit deeper what is happening.
Unhandled exception at 0x000007F6C6DE91E7 in MCServer_debug.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000A4538B3000).
Most complex was to add support of variable number of arguments - e.g. in cLuaState / Call. Defines looks so afwul, may be better would be to wait for laptop to arrive and actually install vs2013.
But this kind of trick is achievable with vs2012:
MacroArg.h:
#pragma once
//
// Retrieve the type
//
// TYPEOF( (ArgType) argName ) => ArgType
//
// http://stackoverflow.com/questions/41453...pplication
//
#define TYPEOF(x) TYPEOF_PASS2(TYPEOF_PASS1 x,)
//
// => TYPEOF_PASS2(TYPEOF_PASS1 (ArgType) argName,)
//
#define TYPEOF_PASS1(...) (__VA_ARGS__),
//
// => TYPEOF_PASS2( (ArgType), argName,)
//
#define TYPEOF_PASS2(...) TYPEOF_PASS3((__VA_ARGS__))
//
// => TYPEOF_PASS2(( (ArgType), argName,))
//
#define TYPEOF_PASS3(x) TYPEOF_PASS4 x
//
// => TYPEOF_PASS4 ( (ArgType), argName,)
//
#define TYPEOF_PASS4(x, ...) REM x
//
// => REM (ArgType)
//
#define REM(...) __VA_ARGS__
//
// => ArgType
//
//
// This counts the number of args:
//
// NARGS( (ArgType1) argName1, (ArgType2) argName2 ) => 2
//
#define NARGS(...) NARGS_PASS1((__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
//
// => NARGS_PASS1(( (ArgType1) argName1, (ArgType2) argName2, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
//
#define NARGS_PASS1(x) NARGS_PASS2 x
//
// => NARGS_PASS2( (ArgType1) argName1, (ArgType2) argName2, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
//
#define NARGS_PASS2(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,N,...) N
//
// => 2
//
// Show the type without parenthesis
//
// PAIR( (ArgType1) argName1 ) => ArgType1 argName1
//
#define PAIR(x) REM x
//
// => REM (ArgType1) argName1
//
// => ArgType1 argName1
//
//
// Strip off the type
//
// ARGNAME( (ArgType1) argName1 ) => argName1
//
#define ARGNAME(x) EAT x
//
// => EAT (ArgType1) argName1
//
#define EAT(...)
//
// => argName1
//
//
// This will call a macro on each argument passed in
//
// APPLY(typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 )
//
#define APPLY(macro, ...) APPLY_PASS1(CAT(APPLY_, NARGS(__VA_ARGS__)), (macro, __VA_ARGS__))
//
// => APPLY_PASS1(CAT(APPLY_, NARGS( (ArgType1) argName1, (ArgType1) argName2 ) ), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
// => APPLY_PASS1(CAT(APPLY_, 2), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT(x, y) CAT_PASS1((x, y))
//
// => APPLY_PASS1(CAT_PASS1((APPLY_, 2)), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT_PASS1(x) PRIMITIVE_CAT x
//
// => APPLY_PASS1(PRIMITIVE_CAT (APPLY_, 2), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define PRIMITIVE_CAT(x, y) x ## y
//
// => APPLY_PASS1( APPLY_2 ), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define APPLY_PASS1(m, x) m x
//
// => APPLY_2 (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) )
//
#define APPLY_1(m, x1) m(x1)
#define APPLY_2(m, x1, x2) m(x1), m(x2)
//
// => typename TYPEOF( (ArgType1) argName1 ), typename TYPEOF( (ArgType1) argName2 ) )
// => typename ArgType1, typename ArgType1
//
#define APPLY_3(m, x1, x2, x3) m(x1), m(x2), m(x3)
#define APPLY_4(m, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
#define APPLY_5(m, x1, x2, x3, x4, x5) m(x1), m(x2), m(x3), m(x4), m(x5)
#define APPLY_6(m, x1, x2, x3, x4, x5, x6) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
#define APPLY_7(m, x1, x2, x3, x4, x5, x6, x7) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
#define APPLY_8(m, x1, x2, x3, x4, x5, x6, x7, x8) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
#define APPLY_9(m, x1, x2, x3, x4, x5, x6, x7, x8, x9) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
#define APPLY_10(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10)
#define APPLY_11(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11)
#define APPLY_12(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12)
#define APPLY_13(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13)
#define APPLY_14(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14)
#define APPLY_15(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14), m(x15)
//
// ARGX(1) => (Arg1) arg1
//
#define ARGX(index) (Arg##index) arg##index
//
// Defines same function with different amount of arguments.
//
#define DEFINE_MULTIARG_FUNC(macro) \
macro ( ARGX(1) ); \
macro ( ARGX(1), ARGX(2) ); \
macro ( ARGX(1), ARGX(2), ARGX(3) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14), ARGX(15) ); \
Test code could look like this:
#define DEFINE_DoTestFunc(...) \
template < APPLY(typename TYPEOF, __VA_ARGS__ ) > \
void DoTest( APPLY(PAIR, __VA_ARGS__ ) ) \
{ \
APPLY(printf, \
APPLY( ARGNAME, __VA_ARGS__ ) \
); \
printf("\r\n"); \
}
//
// In theory generates code like:
// printf(arg1), printf(arg2), ;
// Works well with commas ',' as well as with semicolon ';'
//
DEFINE_MULTIARG_FUNC(DEFINE_DoTestFunc)
and actual function call like this:
DoTest("arg 1", "arg2");
DoTest("arg 1", "arg2", "arg3x");
But in similar technique it's possible to replace function like this:
template <typename FnT, typename... Args>
bool Call(const FnT & a_Function, Args &&... args)
{
if (!PushFunction(a_Function))
{
// Pushing the function failed
return false;
}
return PushCallPop(args...);
}
With two part implementation:
template <typename FnT >
bool Call(const FnT & a_Function)
{
if (!PushFunction(a_Function))
return false;
return PushCallPop();
}
#define DEFINE_CallFunc(...) \
template <typename FnT, APPLY(typename TYPEOF, __VA_ARGS__ ) > \
bool Call(const FnT & a_Function, APPLY(PAIR, __VA_ARGS__ ) ) \
{ \
if (!PushFunction(a_Function)) \
return false; \
return PushCallPop( APPLY(ARGNAME, __VA_ARGS__ ) ); \
}
DEFINE_MULTIARG_FUNC(DEFINE_CallFunc)
Does anyone here have skype - e.g. in case if I want to ask some questions related to mcserver code ?
Apparently I've managed to compile the code, however I have made quit serious cracks in code, so I suspect I've managed to brake it down - because it now claims about stack overflow exception, meanwhile according to call stack it did not reach deeply enough. I probably need to debug bit deeper what is happening.
Unhandled exception at 0x000007F6C6DE91E7 in MCServer_debug.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000A4538B3000).
Most complex was to add support of variable number of arguments - e.g. in cLuaState / Call. Defines looks so afwul, may be better would be to wait for laptop to arrive and actually install vs2013.
But this kind of trick is achievable with vs2012:
MacroArg.h:
#pragma once
//
// Retrieve the type
//
// TYPEOF( (ArgType) argName ) => ArgType
//
// http://stackoverflow.com/questions/41453...pplication
//
#define TYPEOF(x) TYPEOF_PASS2(TYPEOF_PASS1 x,)
//
// => TYPEOF_PASS2(TYPEOF_PASS1 (ArgType) argName,)
//
#define TYPEOF_PASS1(...) (__VA_ARGS__),
//
// => TYPEOF_PASS2( (ArgType), argName,)
//
#define TYPEOF_PASS2(...) TYPEOF_PASS3((__VA_ARGS__))
//
// => TYPEOF_PASS2(( (ArgType), argName,))
//
#define TYPEOF_PASS3(x) TYPEOF_PASS4 x
//
// => TYPEOF_PASS4 ( (ArgType), argName,)
//
#define TYPEOF_PASS4(x, ...) REM x
//
// => REM (ArgType)
//
#define REM(...) __VA_ARGS__
//
// => ArgType
//
//
// This counts the number of args:
//
// NARGS( (ArgType1) argName1, (ArgType2) argName2 ) => 2
//
#define NARGS(...) NARGS_PASS1((__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
//
// => NARGS_PASS1(( (ArgType1) argName1, (ArgType2) argName2, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
//
#define NARGS_PASS1(x) NARGS_PASS2 x
//
// => NARGS_PASS2( (ArgType1) argName1, (ArgType2) argName2, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
//
#define NARGS_PASS2(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,N,...) N
//
// => 2
//
// Show the type without parenthesis
//
// PAIR( (ArgType1) argName1 ) => ArgType1 argName1
//
#define PAIR(x) REM x
//
// => REM (ArgType1) argName1
//
// => ArgType1 argName1
//
//
// Strip off the type
//
// ARGNAME( (ArgType1) argName1 ) => argName1
//
#define ARGNAME(x) EAT x
//
// => EAT (ArgType1) argName1
//
#define EAT(...)
//
// => argName1
//
//
// This will call a macro on each argument passed in
//
// APPLY(typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 )
//
#define APPLY(macro, ...) APPLY_PASS1(CAT(APPLY_, NARGS(__VA_ARGS__)), (macro, __VA_ARGS__))
//
// => APPLY_PASS1(CAT(APPLY_, NARGS( (ArgType1) argName1, (ArgType1) argName2 ) ), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
// => APPLY_PASS1(CAT(APPLY_, 2), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT(x, y) CAT_PASS1((x, y))
//
// => APPLY_PASS1(CAT_PASS1((APPLY_, 2)), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT_PASS1(x) PRIMITIVE_CAT x
//
// => APPLY_PASS1(PRIMITIVE_CAT (APPLY_, 2), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define PRIMITIVE_CAT(x, y) x ## y
//
// => APPLY_PASS1( APPLY_2 ), (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define APPLY_PASS1(m, x) m x
//
// => APPLY_2 (typename TYPEOF, (ArgType1) argName1, (ArgType1) argName2 ) )
//
#define APPLY_1(m, x1) m(x1)
#define APPLY_2(m, x1, x2) m(x1), m(x2)
//
// => typename TYPEOF( (ArgType1) argName1 ), typename TYPEOF( (ArgType1) argName2 ) )
// => typename ArgType1, typename ArgType1
//
#define APPLY_3(m, x1, x2, x3) m(x1), m(x2), m(x3)
#define APPLY_4(m, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
#define APPLY_5(m, x1, x2, x3, x4, x5) m(x1), m(x2), m(x3), m(x4), m(x5)
#define APPLY_6(m, x1, x2, x3, x4, x5, x6) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
#define APPLY_7(m, x1, x2, x3, x4, x5, x6, x7) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
#define APPLY_8(m, x1, x2, x3, x4, x5, x6, x7, x8) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
#define APPLY_9(m, x1, x2, x3, x4, x5, x6, x7, x8, x9) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
#define APPLY_10(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10)
#define APPLY_11(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11)
#define APPLY_12(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12)
#define APPLY_13(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13)
#define APPLY_14(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14)
#define APPLY_15(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14), m(x15)
//
// ARGX(1) => (Arg1) arg1
//
#define ARGX(index) (Arg##index) arg##index
//
// Defines same function with different amount of arguments.
//
#define DEFINE_MULTIARG_FUNC(macro) \
macro ( ARGX(1) ); \
macro ( ARGX(1), ARGX(2) ); \
macro ( ARGX(1), ARGX(2), ARGX(3) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14), ARGX(15) ); \
Test code could look like this:
#define DEFINE_DoTestFunc(...) \
template < APPLY(typename TYPEOF, __VA_ARGS__ ) > \
void DoTest( APPLY(PAIR, __VA_ARGS__ ) ) \
{ \
APPLY(printf, \
APPLY( ARGNAME, __VA_ARGS__ ) \
); \
printf("\r\n"); \
}
//
// In theory generates code like:
// printf(arg1), printf(arg2), ;
// Works well with commas ',' as well as with semicolon ';'
//
DEFINE_MULTIARG_FUNC(DEFINE_DoTestFunc)
and actual function call like this:
DoTest("arg 1", "arg2");
DoTest("arg 1", "arg2", "arg3x");
But in similar technique it's possible to replace function like this:
template <typename FnT, typename... Args>
bool Call(const FnT & a_Function, Args &&... args)
{
if (!PushFunction(a_Function))
{
// Pushing the function failed
return false;
}
return PushCallPop(args...);
}
With two part implementation:
template <typename FnT >
bool Call(const FnT & a_Function)
{
if (!PushFunction(a_Function))
return false;
return PushCallPop();
}
#define DEFINE_CallFunc(...) \
template <typename FnT, APPLY(typename TYPEOF, __VA_ARGS__ ) > \
bool Call(const FnT & a_Function, APPLY(PAIR, __VA_ARGS__ ) ) \
{ \
if (!PushFunction(a_Function)) \
return false; \
return PushCallPop( APPLY(ARGNAME, __VA_ARGS__ ) ); \
}
DEFINE_MULTIARG_FUNC(DEFINE_CallFunc)
Does anyone here have skype - e.g. in case if I want to ask some questions related to mcserver code ?