如何保证在粘贴之前参数完全宏扩展?
我有一个通用宏:
#define mSwitch( Root, Case ) Root##_Case_##Case
#define mSpecialDisplay( what, Val ) mSwitch(mSpecialDisplay,what)(Val)
#define mSpecialDisplay_Case_Int(Val) ...do stuff
#define mSpecialDisplay_Case_Float(Val) ...do stuff
...more special cases
如何保证变量 Case
在粘贴到 mSwitch
中之前完全展开?
如果 mSwitch
传递一个文字值,它工作得很好,但如果有多层间接或中间操作,mSwitch 最终会在完全展开之前粘贴其中一层。
我正在使用 MSVC 2005
。
有没有一种简单的方法可以确保在粘贴完成之前完全展开参数?
谢天谢地
,给出一个例子也许并不难:
#define mMDebugInfo( ... ) mMDebugExp( mMDebugInfo_( 0, __VA_ARGS__ ) )
#define mMDebugInfo_( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (C, __VA_ARGS__) )
#define mMDebugInfoRep( C, ... ) mMXP##C( mMDebugInfo_ )mMXP##C((mMIInc(C),__VA_ARGS__)) //(mMExpDo(mMGlue( mM, C)##DebugInfo_(mMIInc(C),__VA_ARGS__))
#define mMDebugInfo1( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (mMIInc(C), __VA_ARGS__) )
#define mMDebugInfo_Case_Nil(...) [Nil]
#define mMDebugInfo_Case_CntArgs(C,I,...)
mMDebugInfoRep(C,I),mMDebugInfoRep(C,__VA_ARGS__)
#define mMDebugInfo_Case_PrnNull(C,I) [()]
#define mMDebugInfo_Case_Prn(C,I) ( mMDebugInfoRep(C,mMDPrn(I)) )
#define mMDebugInfo_Case_ActFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, I, mMTrait_Fn_mM##I) )
#define mMDebugInfo_Case_PassFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, mMTrait_Fn_mM##I) )
#define mMDebugInfo_Case_Fn( C,Name, Reg, ArgCnt, PArgs ) [Name:ArgCnt]( mMAritize( mMSwitch( mMDebugInfo_Case_Fn, ArgCnt ), (C, mMDPrn( PArgs ) )) )
#define mMDebugInfo_Case_Fn_Case_V(C, _1, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, __VA_ARGS__)
#define mMDebugInfo_Case_Fn_Case_0(...) [Nil]
#define mMDebugInfo_Case_Fn_Case_1(C, _1, ...) mMDebugInfoRep(C, _1)
#define mMDebugInfo_Case_Fn_Case_2(C, _1, _2, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2)
#define mMDebugInfo_Case_Fn_Case_3(C, _1, _2, _3, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3)
#define mMDebugInfo_Case_Fn_Case_4(C, _1, _2, _3, _4, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3), mMDebugInfoRep(C, _4)
#define mMDebugInfo_Case_Int(C,I) [Num:I]
#define mMDebugInfo_Case_Digit(C,I) [Dig:I]
#define mMDebugInfo_Case_Bool(C,I) [Bin:I]
#define mMDebugInfo_Case_CCode(C,I) [CCd:I]
#define mMDebugInfo_Case_UToken(C,I) [UT:I]
这是调试代码,递归解析嵌套表达式没有问题,例如:
DebugInfo( BInt( BNot( IAdd(4,BNot(IAdd(6,7)) ) ) ) );
"
产生:
"[BInt:1]( [BNot:1]( [IAdd:2]( [Dig:4], [BNot:1]( [IAdd:2]( [Dig:6], [Dig:7] ) ) ) ) )"
示例表达式中的宏函数处于非活动形式。当我激活表单时,问题就发生了 - 各个参数的解析链可能会变得任意长,并且在使用它们之前它们不会得到完全解决。
I have a general macro:
#define mSwitch( Root, Case ) Root##_Case_##Case
#define mSpecialDisplay( what, Val ) mSwitch(mSpecialDisplay,what)(Val)
#define mSpecialDisplay_Case_Int(Val) ...do stuff
#define mSpecialDisplay_Case_Float(Val) ...do stuff
...more special cases
how do I guarantee that the variable Case
is fully expanded before it gets pasted in mSwitch
?
It works fine if mSwitch
is passed a literal value, but if there are several layers of indirection, or intermediary operations, mSwitch ends up pasting one of those before they get fully expanded.
I'm using MSVC 2005
.
Is there a simple way to make sure a parameter is fully expanded before pasting is done?
Thanks
well, it isn't that hard to give an example maybe:
#define mMDebugInfo( ... ) mMDebugExp( mMDebugInfo_( 0, __VA_ARGS__ ) )
#define mMDebugInfo_( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (C, __VA_ARGS__) )
#define mMDebugInfoRep( C, ... ) mMXP##C( mMDebugInfo_ )mMXP##C((mMIInc(C),__VA_ARGS__)) //(mMExpDo(mMGlue( mM, C)##DebugInfo_(mMIInc(C),__VA_ARGS__))
#define mMDebugInfo1( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (mMIInc(C), __VA_ARGS__) )
#define mMDebugInfo_Case_Nil(...) [Nil]
#define mMDebugInfo_Case_CntArgs(C,I,...)
mMDebugInfoRep(C,I),mMDebugInfoRep(C,__VA_ARGS__)
#define mMDebugInfo_Case_PrnNull(C,I) [()]
#define mMDebugInfo_Case_Prn(C,I) ( mMDebugInfoRep(C,mMDPrn(I)) )
#define mMDebugInfo_Case_ActFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, I, mMTrait_Fn_mM##I) )
#define mMDebugInfo_Case_PassFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, mMTrait_Fn_mM##I) )
#define mMDebugInfo_Case_Fn( C,Name, Reg, ArgCnt, PArgs ) [Name:ArgCnt]( mMAritize( mMSwitch( mMDebugInfo_Case_Fn, ArgCnt ), (C, mMDPrn( PArgs ) )) )
#define mMDebugInfo_Case_Fn_Case_V(C, _1, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, __VA_ARGS__)
#define mMDebugInfo_Case_Fn_Case_0(...) [Nil]
#define mMDebugInfo_Case_Fn_Case_1(C, _1, ...) mMDebugInfoRep(C, _1)
#define mMDebugInfo_Case_Fn_Case_2(C, _1, _2, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2)
#define mMDebugInfo_Case_Fn_Case_3(C, _1, _2, _3, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3)
#define mMDebugInfo_Case_Fn_Case_4(C, _1, _2, _3, _4, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3), mMDebugInfoRep(C, _4)
#define mMDebugInfo_Case_Int(C,I) [Num:I]
#define mMDebugInfo_Case_Digit(C,I) [Dig:I]
#define mMDebugInfo_Case_Bool(C,I) [Bin:I]
#define mMDebugInfo_Case_CCode(C,I) [CCd:I]
#define mMDebugInfo_Case_UToken(C,I) [UT:I]
this is debug code that has no problems recursively parsing nested expressions like:
DebugInfo( BInt( BNot( IAdd(4,BNot(IAdd(6,7)) ) ) ) );
"
which yields:
"[BInt:1]( [BNot:1]( [IAdd:2]( [Dig:4], [BNot:1]( [IAdd:2]( [Dig:6], [Dig:7] ) ) ) ) )"
The macro functions in the example expression are in inactive form. The problem is happening when I activate the form - the parse chain for the individual arguments can get arbitrarily long and they aren't getting resolved completely before they are getting used.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是通常的习惯用法:
C 预处理器宏的所有参数在宏本身扩展之前都已完全扩展,除非
#
或##
运算符应用于它们;那么它们就不会被扩展。因此,要在##
之前获得完全扩展,您可以通过不使用##
的包装宏传递参数。This is the usual idiom for this:
All of the arguments to a C preprocessor macro are fully expanded before the macro itself is expanded, unless the
#
or##
operator is applied to them; then they're not expanded. So to get full expansion before##
, you pass the arguments through a wrapper macro that doesn't use##
.