在C ++中, 我需要定义一个宏。 该宏将参数作为代码的“块”。
我们可以安全地使用几行代码作为宏功能的参数吗?
我问自己是否:
#define MY_MACRO( expr ) DOSOMETHING( (expr) ); DOANOTHERTHING( (expr) ); // etc...
int my_function() {
int o = RandomNumber();
MY_MACRO(
int k = AFunction();
k++;
AnotherFunction( k + o ); // here I need to keep the context of the call
);
}
我们不能使用仿函数,因为我们需要访问调用的上下文。 我们不能使用lambda(snif),因为我们使用的是一个不提供它的旧编译器(我们无法更改它)。
答案 0 :(得分:9)
16.3 / 9:
在预处理序列中 令牌组成一个调用 功能一样的宏,新线是 被认为是正常的白色空间 字符。
所以多线宏调用一般都没问题。当然,如果DOSOMETHING
和DOANOTHERTHING
没有为范围引入大括号,那么您的特定示例将重新定义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));
}
您还可以通过引用捕获变量(通常使用指针作为数据成员而不是引用,以便可以对仿函数进行复制分配)。
如果通过“context”,你的意思是例如宏参数和/或宏体可能包含break
或goto
,因此需要在调用者的词法范围内那么你不能使用仿函数或lambda。羞耻; - )
答案 1 :(得分:2)
使它工作的方式(至少对于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;
....
}
});
答案 2 :(得分:1)
我认为你需要使用额外的括号来使你的表达式看起来像一个参数,它不会被预处理器分解,即更像是这样:
#define MY_MACRO( (expr) ) DOSOMETHING( (expr) ); DOANOTHERTHING( (expr) ); // etc...
int my_function() {
MY_MACRO(
(int k = AFunction();
k++;
AnotherFunction( k );)
);
}
虽然我实际上没有尝试过。
答案 3 :(得分:1)
在C ++中你应该使用仿函数! ;)
struct ninja
{
void operator()() const
{
int k = AFunction();
k++;
AnotherFunction( k );
}
};
template <typename Functor>
void do_something(Functor const& f)
{
f();
}
template <typename Functor>
void do_otherthing(Functor const& f)
{
f();
}
int my_function()
{
ninja foo;
do_something(foo);
do_otherthing(foo);
}
答案 4 :(得分:0)
我看到的主要问题是expr
根本不是表达式。它甚至包含一个声明。显然,k
中定义的两个变量my_function
会出现问题。
如果你可以使用C ++ 0x(例如VS2010,GCC4.6),那么你可以使用lambda来捕获上下文。并不是说您需要为这样一个简单的案例捕获上下文,也不需要模板,您的宏只需要std::function<void(void)>
。
答案 5 :(得分:0)
在多个参数的情况下,具有多行参数的宏也可以,它甚至允许使用&#34;逗号&#34;在里面,但我强烈建议使用&#34;逗号&#34;如果它不是机器的模糊,它肯定是对人类的模糊:
#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;
}