I've got a large C++20 codebase with a bunch of macro instantiations that are simple variations of this example:
void main() {
MAKE_VAR(int myInt);
MAKE_VAR(CMyClass myClass);
MAKE_VAR(CMyClass *pMyClass);
};
Because the utility of the macro is part of a process that exists outside of the actual compilation of the code, the #define
is currently trivial:
#define MAKE_VAR(var) var
Which means the resulting code after expansion is simply:
void main() {
int myInt;
CMyClass myClass;
CMyClass *pMyClass;
};
But, I'm trying to add more smarts to MAKE_VAR
that depends upon the type of the variable, and for compatibility reasons I'm unable to change that macro signature (eg having the macro take the type and name as separate arguments).
So, my question is whether or not there is some incantation whereby I can take the var
macro argument and produce just the type of that argument for use as a template parameter in a subsequent bit of generated code. Note that I do not need to get the name out (nor do I believe that's possible with standard C++20).
That is, I would like to come up with a macro definition such that the above MyStruct
example expands into something like this (with whatever extra boilerplate necessary):
void main() {
int myInt;
DoThing<int>();
CMyClass myClass;
DoThing<CMyClass>();
CMyClass *pMyClass;
DoThing<CMyClass *>();
};
My first attempts revolved around trying to get something I could pass into decltype
, but I wasn't able to find any such incantation that permits the name being present.
I've gotten close to a solution with the following approach but I have a different problem, where it only works once (because FakeFunc
doesn't have a unique name per instance - normally I would use something akin to __COUNTER__
or similar but I need it to work across both lines here):
template <typename Sig> struct ArgType;
template <typename Arg> struct ArgType<void(Arg)> { using type = Arg; };
#define MAKE_VAR(var) \
var; \
typedef void FakeFunc( var ); \
DoThing<typename ArgType<FakeFunc>::type>();
void main() {
MAKE_VAR(int myInt);
MAKE_VAR(unsigned myUInt);
};
// Macro expands to:
void main() {
int myInt;
typedef void FakeFunc( int myInt );
DoThing<typename ArgType<FakeFunc>::type>();
unsigned myUInt;
typedef void FakeFunc( unsigned myUInt );
DoThing<typename ArgType<FakeFunc>::type>();
};
Any thoughts on finishing out this approach or using a different approach?
EDIT: Closing question for now because I need to clarify why I can't just put FakeFunc
and DoThing
in a local scope, which is a nuance I didn't capture in this simplified question...
You don't need to give a name to the function:
template <typename Sig> struct ArgType;
template <typename Arg> struct ArgType<void(*)(Arg)> { using type = Arg; };
template <typename T> void DoThing() {}
#define MAKE_VAR(var) \
var; \
DoThing<typename ArgType<void (*)( var )>::type>();
int main() {
MAKE_VAR(int x)
MAKE_VAR(unsigned y)
}
The macros expand to
int x; DoThing<typename ArgType<void (*)( int x )>::type>();
unsigned y; DoThing<typename ArgType<void (*)( unsigned y )>::type>();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.