我正在尝试做类似的事情:
custommacro x;
将扩展为:
declareSomething; int x; declareOtherthing;
这甚至可能吗?
我已经用operator=
欺骗了一次,表现得像那样,但声明无法完成。
答案 0 :(得分:6)
只要您愿意接受两个补充,您就可以忽略括号:
e.g。正是如此:
#define LPAREN (
#define echo ECHO_MACRO LPAREN
#define done )
#define ECHO_MACRO(X) std::cout << (X) << "\n"
#define DSL(X) X
...
DSL(
echo "Look ma, no brains!" done;
)
...
原因:
done
宏一样,它将扩展为包含必要的关闭paren的表单echo ... done
形式看起来不像是对预处理器的宏调用,所以当预处理器进入时,它没有被标记为扩展,并且我们是否将parens放入是不相关的。因此,仅使用echo ... done
将在文本DSL
)包裹整个块将导致调用要在此重新扫描过程中扩展ECHO_MACRO(DSL
对结果不做任何操作:它只是为了强制重新扫描而存在)(
后面的echo
扩展中隐藏LPAREN
,否则宏体中不匹配的括号会混淆预处理器如果您想为这些命令创建一个完整的特定于域的语言,您还可以通过使核心命令更加笨拙来减少done
命令的数量:
#define LPAREN (
#define begin NO_OP LPAREN 0
#define done );
#define echo ); ECHO_MACRO LPAREN
#define write ); WRITE_MACRO LPAREN
#define add ); ADD_MACRO LPAREN
#define sub ); SUB_MACRO LPAREN
#define NO_OP(X)
#define ECHO_MACRO(X) std::cout << (X) << "\n"
#define WRITE_MACRO(X) std::cout << (X)
#define ADD_MACRO(D, L, R) (D) = (L) + (R)
#define SUB_MACRO(D, L, R) (D) = (L) - (R)
#define DSL(X) DSL_2 X
#define DSL_2(X) X
int main(void) {
int a, b;
DSL((
begin
add a, 42, 47
sub b, 64, 50
write "a is: "
echo a
write "b is: "
echo b
done
))
return 0;
}
在这种形式中,每个命令都预先设计为关闭前面的命令,因此只有最后一个命令需要done
;你需要一个begin
行,这样就可以打开一个关闭第一个实际操作的命令,否则parens会不匹配。
C语言比在C ++中容易得多,因为C的预处理器功能更强大(它支持__VA_ARGS__
,这对于复杂的宏元编程非常重要)。
哦,是的,还有一件事 -
...请永远在实际代码中执行此操作。
答案 1 :(得分:2)
我明白你要做什么,而且根本无法完成。宏只是文本替换,它不知道后面会发生什么,所以尝试custommacro x
会扩展到custommacro
是什么,一个空格,然后是x
,它只是不会在语义上工作。
另外,关于你的echo
hack:在C ++中使用运算符实际上非常简单:
#include <iostream>
#define echo std::cout <<
int main()
{
echo "Hello World!";
}
但是你真的不应该编写这样的代码(也就是说,使用宏和伪问题回应)。您应该编写符合语言语法的代码以及您尝试执行的语义。如果要使用std::cout
写入标准输出。此外,如果您想使用echo
,请创建一个名为echo
的函数,在内部调用std::cout
,但不要破解该语言的功能来创建自己的函数。
答案 2 :(得分:1)
您可以使用for循环和GnuC语句表达式扩展。
#define MY_MACRO\
FOR_MACRO(_uniq##__COUNTER__##name,{/*declareSomething*/ },{ /* declareOtherthing */ }) int
#define FOR_MACRO(NAME,FST_BLOCK,SND_BLOCK)\
for(int NAME = ({FST_BLOCK ;0;}); NAME<1 ; NAME++,(SND_BLOCK))
它实际上是卫生的,但这意味着无论你在这些代码块中做什么都不会逃避for循环范围。