void main()
{
int xyz = 123; // original value
{ // code block starts
xyz++;
if(xyz < 1000)
xyz = 1;
} // code block ends
int original_value = xyz; // should be 123
}
void main()
{
int xyz = 123; // original value
MACRO_NAME(xyz = 123) // the macro takes the code code that should be executed at the end of the block.
{ // code block starts
xyz++;
if(xyz < 1000)
xyz = 1;
} // code block ends << how to make the macro execute the "xyz = 123" statement?
int original_value = xyz; // should be 123
}
只有第一个main()
有效
我认为这些评论解释了这个问题。
它不需要是一个宏,但对我来说,它听起来像是一个经典的“宏观需要”的案例。
顺便说一下,有BOOST_FOREACH
宏/库,我认为它与我想要实现的完全一样,但是找到我需要的东西对我来说太复杂了。
从其介绍性手册页中,举例:
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
答案 0 :(得分:8)
最简洁的方法是使用RAII容器重置值:
// Assumes T's assignment does not throw
template <typename T> struct ResetValue
{
ResetValue(T& o, T v) : object_(o), value_(v) { }
~ResetValue() { object_ = value_; }
T& object_;
T value_;
};
用作:
{
ResetValue<int> resetter(xyz, 123);
// ...
}
当块结束时,将调用析构函数,将对象重置为指定值。
如果确实想要使用宏,只要它是一个相对简单的表达式,就可以使用for-block执行此操作:
for (bool b = false; b == false; b = true, (xyz = 123))
{
// ...
}
可以变成一个宏:
#define DO_AFTER_BLOCK(expr) \
for (bool DO_AFTER_BLOCK_FLAG = false; \
DO_AFTER_BLOCK_FLAG == false; \
DO_AFTER_BLOCK_FLAG = true, (expr))
用作:
DO_AFTER_BLOCK(xyz = 123)
{
// ...
}
我并不认为宏观方法是个好主意;如果我在生产源代码中看到这个,我可能会觉得很困惑。
答案 1 :(得分:2)
您不一定需要宏 - 您可以使用内部范围变量:
#include <stdio.h>
int main(void)
{
int xyz = 123;
printf("xyz = %d\n", xyz);
{
int pqr = xyz;
int xyz = pqr;
printf("xyz = %d\n", xyz);
xyz++;
if (xyz < 1000)
xyz = 1;
printf("xyz = %d\n", xyz);
}
printf("xyz = %d\n", xyz);
return(0);
}
这会产生输出:
xyz = 123
xyz = 123
xyz = 1
xyz = 123
如果您使用GCC和-Wshadow
进行编译,则会收到警告;否则,它编译清洁。
你不能可靠地在内部块中写int xyz = xyz;
;一旦'='被解析,声明就完成了,因此初始化器是内部'xyz',而不是外部。然而,这两步舞蹈有效。
这主要是因为它需要修改代码块。
如果块中有副作用 - 就像上面的print语句一样 - 你可以调用一个包含内部块的函数。如果块中没有副作用,为什么要执行它。
#include <stdio.h>
static void inner(int xyz)
{
printf("xyz = %d\n", xyz);
xyz++;
if (xyz < 1000)
xyz = 1;
printf("xyz = %d\n", xyz);
}
int main(void)
{
int xyz = 123;
printf("xyz = %d\n", xyz);
inner(xyz);
printf("xyz = %d\n", xyz);
return(0);
}
答案 2 :(得分:0)
除非将循环放在宏中,否则不能使宏在循环后执行命令。并认真?只做一个范围变量会更好。
template<typename T> class CallFunctionOnScopeExit {
T t;
public:
CallFunctionOnScopeExit(T tt) : t(tt) {}
~CallFunctionOnScopeExit() { t(); }
};
在例外等情况下保证,而宏版本绝对不是。我更喜欢将此模式用于异常保证,因为它比仅复制int更灵活。