Как я могу гарантировать полное расширение макроса параметра перед вставкой? - PullRequest
7 голосов
/ 11 июля 2010

У меня есть общий макрос:

#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] ) ) ) ) )"

Функции макросав примере выражения находятся в неактивной форме.Проблема возникает, когда я активирую форму - цепочка разбора для отдельных аргументов может быть произвольно длинной, и они не решаются полностью, пока не привыкнут.

1 Ответ

10 голосов
/ 11 июля 2010

Это обычная идиома для этого:

#define mSwitch(Root, Case) mSwitch_(Root, Case)
#define mSwitch_(Root, Case) Root##_Case_##Case

Все аргументы макроса препроцессора C полностью раскрываются перед раскрытием самого макроса, , если #или к ним применяется оператор ##;тогда они не расширены.Таким образом, чтобы получить полное раскрытие до ##, вы передаете аргументы через макрос-оболочку, который не использует ##.

...