具有多行参数的宏函数? C++中的P> 我需要定义一个宏。 该宏将以代码的“块”作为参数
我们可以安全地使用几行代码作为宏函数的参数吗? 我在问自己:具有多行参数的宏函数? C++中的P> 我需要定义一个宏。 该宏将以代码的“块”作为参数,c++,macros,C++,Macros,我们可以安全地使用几行代码作为宏函数的参数吗? 我在问自己: 以下代码是否有效,标准定义为有效,如“跨平台”中所述 有没有更好的方法来做同样的事情(我不能在那里使用模板函数,因为我需要上下文) 我们不能使用函子,因为我们需要访问调用的上下文。 我们不能使用lambda(snif),因为我们使用的是一个旧的编译器,它不提供lambda(而且我们不能更改它)。我认为您需要使用额外的括号,使表达式看起来像一个不会被预处理器分解的参数,也就是说,像这样做: #define MY_MACRO( (exp
我们不能使用函子,因为我们需要访问调用的上下文。
我们不能使用lambda(snif),因为我们使用的是一个旧的编译器,它不提供lambda(而且我们不能更改它)。我认为您需要使用额外的括号,使表达式看起来像一个不会被预处理器分解的参数,也就是说,像这样做:
#define MY_MACRO( (expr) ) DOSOMETHING( (expr) ); DOANOTHERTHING( (expr) ); // etc...
int my_function() {
MY_MACRO(
(int k = AFunction();
k++;
AnotherFunction( k );)
);
}
虽然我还没有尝试过。
在C++中,你应该使用函子!!p>struct忍者
{
void运算符()()常量
{
int k=a函数();
k++;
另一个函数(k);
}
};
模板
void do_something(函子const&f)
{
f();
}
模板
void do_otherthing(函子const&f)
{
f();
}
int my_函数()
{
忍者富;
做点什么(foo);
做其他事情(foo);
}
我看到的主要问题是expr
根本不是一个表达式。它甚至包含一个声明。显然,在my_函数
中定义的两个变量k
会有问题
如果您可以使用C++0x(例如VS2010、GCC4.6),那么您可以使用lambda来捕获上下文。对于这种简单的情况,您不需要捕获上下文,也不需要模板,您的宏只需要一个std::function
16.3/9:
在预处理序列中
组成对
函数类似于宏,新行是
被认为是正常的空白
性格
因此,多行宏调用通常是好的。当然,如果DOSOMETHING
和donothing
没有为范围引入大括号,那么您的特定示例将重新定义k
编辑:
我们不能使用函子,因为我们需要
要访问
呼叫我们不能使用lambda(snif),因为我们使用的是旧的编译器
通常的方法是捕获函子中需要的任何变量,就像lambda一样。lambda所能做的唯一一件函子不能做的事就是“捕获所有内容”,而不必键入,但是编写lambda的人可以看到他们使用的变量,所以这只是方便,如果必须的话,他们可以将它们全部键入。在您的示例中:
struct MyFunctor {
int o;
MyFunctor(int o) : o(o) {}
void operator()() const { // probably not void in practice
int k = AFunction();
k++;
AnotherFunction( k + o );
}
};
template<typename F>
void DoThings(const F &f) {
DOSOMETHING(f());
DOANOTHERTHING(f());
}
int my_function() {
int o = RandomNumber();
DoBothThings(MyFunctor(o));
}
struct MyFunctor{
INTO;
MyFunctor(into):o(o){}
void运算符()()常量{//实际上可能不是void
int k=a函数();
k++;
另一个函数(k+o);
}
};
模板
无效点(常数F&F){
DOSOMETHING(f());
不做任何事(f());
}
int my_函数(){
int o=随机数();
DoBothThings(MyFunctor(o));
}
您还可以通过引用捕获变量(通常使用指针作为数据成员而不是引用,以便可以复制指定函子)
例如,如果“上下文”是指宏参数和/或宏体可能包含break
或goto
,因此需要在调用方的词法范围内,则不能使用函子或lambda。可耻;-) 参数有多行的宏也可以,在多个参数的情况下,它甚至允许在内部使用“逗号”,但我强烈使用“逗号”进行解释,因为如果它对机器来说不是含糊不清的,那么对人类来说肯定是含糊不清的:
#include <iostream>
using namespace std;
#define MACRO2FUN( X, Y) x; y;
void function(int a, int b, int c){
std::cout<<a<<" "<<b<<" "<<c<<std::endl;
}
int main() {
MACRO2FUN(
function(3,4,5),
function(6,7,8)
)
return 0;
}
#包括
使用名称空间std;
#定义MACRO2FUN(X,Y)X;Y
虚函数(inta,intb,intc){
std::cout使其工作的方法(至少对于gcc版本4.8.1(Ubuntu/Linaro 4.8.1-10ubuntu9))是使用括号{}括住宏的实际值
一个有用的例子:
#ifdef DEBUG
#define MYDEBUG(X) (X)
#else
#define MYDEBUG(X)
#endif
MYDEBUG({
if (shit_happens) {
cerr << "help!" << endl;
....
}
});
#ifdef调试
#定义MYDEBUG(X)(X)
#否则
#定义MYDEBUG(X)
#恩迪夫
MYDEBUG({
如果(大便发生){
cerr这个宏有什么用?你试过了吗?发生了什么事?我猜你传递的每个表达式“参数”都需要包含在()
。感谢编辑Paul,我找不到正确的显示方式。@CharlesB:它生成的代码在生成的代码的几个部分插入表达式参数。问题更多的是:我们可以安全地使用几行代码作为宏函数的参数吗?@Paul R:我们正在尝试,但问题更多如果它是由标准定义的(对宏使用多行)如果是跨平台的。@Klaim,如果你解释一下上下文是什么意思,也许会有助于回答问题。例如,你是否需要调用方在DOSOMETHING
和donotherthing
中的所有状态?如果不需要,你不能将你需要的东西封装在一个可以传递给它们的函子中吗?或者在C++0x中,不需要名字吗:[](){int k=a函数();++k,另一个函数(k);}
是的,我们考虑过这一点,但问题是我们需要保留调用的上下文。但是lambda可以解决这个问题,但我们目前无法使用提供lambda功能的编译器TT_utt。我正在更新答案,无论如何,感谢您确认了我的想法。我不太了解这个叫做C++0x的东西…:(Klaim,上下文是什么意思?@ Nim:看看例子,代码需要访问调用函数中的变量。C++ 0x是C++新标准(C++ 2011)的别名。这定义了lambda功能。我也没有尝试过,但我认为逗号是唯一可以分解宏参数的东西。看起来很奇怪,你可以在其中放置分号,而不需要做任何特殊的事情,它仍然是一个恰好包含分号的宏参数。@Steve:啊,好的-这让我很惊讶
#include <iostream>
using namespace std;
#define MACRO2FUN( X, Y) x; y;
void function(int a, int b, int c){
std::cout<<a<<" "<<b<<" "<<c<<std::endl;
}
int main() {
MACRO2FUN(
function(3,4,5),
function(6,7,8)
)
return 0;
}
#ifdef DEBUG
#define MYDEBUG(X) (X)
#else
#define MYDEBUG(X)
#endif
MYDEBUG({
if (shit_happens) {
cerr << "help!" << endl;
....
}
});