如何为宏符号添加前缀?

时间:2013-12-11 08:58:10

标签: c++ macros c-preprocessor

我正在寻找标题中所述问题的一般解决方案。但是,插图考虑我的真实情况。我想得到wstring,就像这样:

L"hello"

但是当我有一个宏时:

#define MACRO(S) ...

和电话:

MACRO("hello") // no L prefix

如何像以前一样定义它来获取wstring

L S

被视为2个符号。

2 个答案:

答案 0 :(得分:5)

您需要粘贴操作符,查找#和##作为预处理器,以激发新的机会来解决问题并创建有趣的新问题。

http://www.cprogramming.com/reference/preprocessor/token-pasting-operator.html

但是针对您的具体问题,请尝试:

#define MACRO(S) L ## S

根据我的个人经验,粘贴操作符是C ++中最好的宏用途之一,因为它为您提供了一些在没有它的情况下无法轻松完成的操作。但与大多数预处理器功能一样,它通常用于恶意。

作为一个历史记录,有早期的C编译器,你可以写#define MACRO(S) L/* */S人们做的,因为他们合法地想要标记粘贴,但它没有正式存在。我相信这些日子的评论黑客明显不适用于标准的预处理器。

答案 1 :(得分:4)

基本

直接的方法是使用预处理器令牌粘贴##预处理器运算符,如下所示:

#define MACRO( s ) L ## s

一般解决方案。

你说你正在寻找一个“通用解决方案”,并且基本的令牌粘贴不是很笼统。

特别是当您想要定义像

这样的长字符串时,简单的宏会变得很笨拙
L"Blah blah\n"
L"Second line\n"
L"Third line"

然后你必须写下例如。

MACRO( "Blah blah\n" )
MACRO( "Second line\n" )
MACRO( "Third line" )

很高兴您可以使用C ++ 11 可变参数宏来支持任意数量的参数,编写上面的文字如下:

MACRO(
    "Blah blah\n",
    "Second line\n",
    "Third line"
    )

MACRO定义为,例如,

#   define WITH_L_PREFIX_( lit )     L##lit
#   define MACRO( ... )              MM_APPLY( WITH_L_PREFIX_, __VA_ARGS__ )

然后问题被简化为定义MM_APPLY,例如像这样:

#define MM_APPLY( macroname, ... ) \
    MM_INVOKE( \
        MM_CONCAT( MM_APPLY_, MM_NARGS( __VA_ARGS__ ) ), \
        ( macroname, __VA_ARGS__ ) \
        )

反过来又减少了定义MM_INVOKEMM_CONCATMM_NARGS和更具体MM_APPLY_1的问题。 MM_APPLY_21,或者你对参数数量的首选限制是什么。其原因主要是支持Visual C ++预处理程序,它不符合标准。

关于生成参数数量的MM_ARGS,请参阅Laurent Deniau的原始代码,“ VA_NARG ”,2006年1月17日,在Usenet组< comp.std.c&gt ;例如存档于(https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/d-6Mj5Lko_s)。

其余的,从MM_APPLY_ n 开始,这些定义看起来像......

#define MM_APPLY_1( macroname, a1 ) \
    MM_INVOKE_B( macroname, (a1) )

#define MM_APPLY_2( macroname, a1, a2 ) \
    MM_INVOKE_B( macroname, (a1) ) \
    MM_APPLY_1( macroname, a2 )

#define MM_APPLY_3( macroname, a1, a2, a3 ) \
    MM_INVOKE_B( macroname, (a1) ) \
    MM_APPLY_2( macroname, a2, a3 )

,再次出于支持特定编译器的原因(这次是g ++)引入了MM_INVOKE_B

#define MM_INVOKE( macro, args ) macro args
#define MM_INVOKE_B( macro, args ) macro args     // For nested invocation with g++.

MM_CONCAT很简单,

#define MM_CONCAT__( a, b )     a ## b
#define MM_CONCAT_( a, b )      MM_CONCAT__( a, b )
#define MM_CONCAT( a, b )       MM_CONCAT_( a, b )

就是这样,粗略。

这构成了一个小的“宏框架”,将操作应用于每个参数。