I want to use variadic macros but I get errors
#define SERVER_RE_1(ServerFunction, Type1) \
{ \
Type1 arg1; \
getData(args, arg1); \
sv. ## ServerFunction ## (ssl, arg1); \
}
#define SERVER_RE_2(ServerFunction, Type1, Type2) \
{ \
Type1 arg1; \
Type2 arg2; \
getData(args, arg1, arg2); \
sv. ## ServerFunction ## (ssl, arg1, arg2); \
}
#define SERVER_RE_3(ServerFunction, Type1, Type2, Type3) \
{ \
Type1 arg1; \
Type2 arg2; \
Type3 arg3; \
getData(args, arg1, arg2, arg3); \
sv. ## ServerFunction ## (ssl, arg1, arg2, arg3); \
}
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define SERVER_RE(...) GET_MACRO(__VA_ARGS__, SERVER_RE_3, SERVER_RE_2, SERVER_RE_1)(__VA_ARGS__)
-
SERVER_RE(signIn, std::string, std::string);
error C2065: 'signIn' : undeclared identifier
error C2275: 'std::string' : illegal use of this type as an expression
-
But SERVER_RE_2 works good.
SERVER_RE2(signIn, std::string, std::string);
Remove the extra ##
, as in replace the lines
sv. ## ServerFunction ## (ssl, arg1, arg2, arg3); \
with
sv. ServerFunction (ssl, arg1, arg2, arg3); \
EDIT
Can you try to compile the following code?
#include <string>
#define SERVER_RE_1(ServerFunction, Type1) \
{ \
Type1 arg1; \
getData(args, arg1); \
sv. ServerFunction (ssl, arg1); \
}
#define SERVER_RE_2(ServerFunction, Type1, Type2) \
{ \
Type1 arg1; \
Type2 arg2; \
getData(args, arg1, arg2); \
sv.ServerFunction(ssl, arg1, arg2); \
}
#define SERVER_RE_3(ServerFunction, Type1, Type2, Type3) \
{ \
Type1 arg1; \
Type2 arg2; \
Type3 arg3; \
getData(args, arg1, arg2, arg3); \
sv.ServerFunction(ssl, arg1, arg2, arg3); \
}
#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define SERVER_RE(...) GET_MACRO(__VA_ARGS__, SERVER_RE_3, SERVER_RE_2, SERVER_RE_1)(__VA_ARGS__)
struct C{
template<class T1>
void signIn(int,T1){}
template<class T1, class T2>
void signIn(int,T1,T2){}
template<class T1, class T2,class T3>
void signIn(int,T1,T2,T3){}
};
template<class T1>
void getData(int,T1){}
template<class T1, class T2>
void getData(int,T1,T2){}
template<class T1, class T2, class T3>
void getData(int,T1,T2,T3){}
int main(){
C sv;
int args=0,ssl=0;
SERVER_RE(signIn, std::string);
SERVER_RE(signIn, std::string, std::string);
SERVER_RE(signIn, std::string, std::string, std::string);
}
This is the full code that compiles - as is - for me in both g++
and clang++
, in both c++11
and c++98
modes
Edit 2
That first warning warning C4003
makes me think that there is a basic problem with variadic macros here.
Indeed, booting my windows and playing around in visual studio, there is a bug in visual studio in variadic macro expantion.
You can see it for yourself with the following code:
#include <stdio.h>
#define AAA(a,b) printf("%d %d\n",a,b)
#define BBB(...) AAA(__VA_ARGS__)
int main(){
AAA(1,2); // works
BBB(3,4); // warning + error
}
But worry not! You can fix it! Use my above code, but replace the line
#define SERVER_RE(...) GET_MACRO(__VA_ARGS__, SERVER_RE_3, SERVER_RE_2, SERVER_RE_1)(__VA_ARGS__)
with
#define GET_MACRO_X(X) GET_MACRO X
#define SERVER_RE(...) GET_MACRO_X((__VA_ARGS__, SERVER_RE_3, SERVER_RE_2, SERVER_RE_1))(__VA_ARGS__)
and that compiles in visual studio! YAY!