C++ 使用C+创建新范围+;宏?
这可能吗?我想写一个宏,使它更容易使用我的一些类的功能 假设我的类中有两个成员函数,setup()和cleanup(),其中setup()为需要在其自身范围内执行的某些操作设置参数,cleanup()执行清理(类似于构造函数和析构函数的概念) 目前,我这样做:C++ 使用C+创建新范围+;宏?,c++,macros,scope,C++,Macros,Scope,这可能吗?我想写一个宏,使它更容易使用我的一些类的功能 假设我的类中有两个成员函数,setup()和cleanup(),其中setup()为需要在其自身范围内执行的某些操作设置参数,cleanup()执行清理(类似于构造函数和析构函数的概念) 目前,我这样做: myClassInstance.setup(); //call the setup function { //start scope //CREATE LOCAL VARS //DO STUFF IN THIS SCOPE
myClassInstance.setup(); //call the setup function
{ //start scope
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
myClassInstance.cleanup(); //cleanup
} //end scope, destroy locals
但是我想做一些类似的事情:
NEWSCOPE(myClassInstance) //calls setup()
{
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
} // calls cleanup() and destroys locals
我的想法是编写一个可以在使用宏时实例化的宏类,并且setup()和cleanup()可以在构造函数/析构函数中实现。。。或者类似的事情
这是思考这个问题的正确方式,还是有另一种方式来编写一个宏,它基本上可以包装用户编写的代码
*编辑*
我修复了命名约定,因为函数名会引起混淆。要创建新的作用域,只需使用匿名块
{
Obj obj;
/*
teh codez
*/
}//obj is deallocated
所以你不需要宏
听起来你应该是构造函数和析构函数,但是如果不知道它们的实际作用,你就很难知道它们是什么
更新:我试着给你一个答案,但我只是咆哮
类似于构造函数和析构函数的概念
对我来说,这听起来像是构造函数和析构函数,当您让构造函数和析构函数进行设置和清理时,操作将自然地、易读地使用RAII执行
另外一件事,你说你的第一个解决方案(我偶然地给你回)是工作的,为什么需要用宏来处理C宏,来模拟C++提供的特征(比如模板和对象)。对于几乎所有的情况,尤其是对于C++11,宏只会使事情变得更糟,更难调试,而且在您的情况下,似乎在执行宏时实际上必须键入更多的内容
我的建议是重新思考为什么您需要一个宏,为什么
setup
和cleanup
不能成为构造函数和析构函数。您可以用与使用RAII获得互斥锁相同的方式来处理此问题。大概是这样的:
class MyClassScopeBlock
{
public:
MyClassScopeBlock( MyClass & c )
: obj(c)
{
obj.startScope();
}
~MyClassScopeBlock()
{
obj.endScope();
}
private:
MyClass & obj;
};
然后将其实例化为作用域块内的局部变量:
{
MyClassScopeBlock block( myClassInstance );
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
}
#define NEWSCOPE(inst) MyClassScopeBlock block(inst)
如果确实需要,可以为其定义一个宏,在范围块内使用:
{
MyClassScopeBlock block( myClassInstance );
//CREATE LOCAL VARS
//DO STUFF IN THIS SCOPE
}
#define NEWSCOPE(inst) MyClassScopeBlock block(inst)
就我个人而言,我宁愿尽可能远离宏。将整个作用域放入宏替换中的更好选择是使用类似于。我已经成功地用以下宏封装了链接的解决方案:
#define FINALLY_NAMED( NAME, ... ) auto && NAME = \
util::finally( [&]() noexcept { __VA_ARGS__ } );
#define FINALLY( ... ) CPLUS_FINALLY_NAMED( guard, __VA_ARGS__ )
#define DO_FINALLY static_cast< void >( guard );
这是异常安全的,cleanup
当且仅当setup
成功完成时执行,就像构造函数/析构函数对一样。但是清理
不能抛出异常
但是如果你想用传统的方式做 可以使用可变宏将整个范围包含在宏中:
#define NEWSCOPE( INSTANCE, ... ) { \
(INSTANCE).setup(); /* call the setup function */ \
{ __VA_ARGS__ } /* paste teh codez here */ \
(INSTANCE).cleanup(); /* call the cleanup function */
我建议不要将cleanup
放在内部作用域中,因为作用域的要点是包含声明和名称,但您希望使用外部作用域中的实例的名称
用法:
{
myClassInstance.setup(); //call the setup function
FINALLY ( myClassInstance.cleanup(); ) //call the cleanup function before exit
// do something
DO_FINALLY // Explicitly note that cleanup happens here. (Only a note.)
}
NEWSCOPE ( myClassInstance,
// Do stuff.
// Multiple declarations, anything can go here as if inside braces.
// (But no #define directives. Down, boy.)
)
在看到BOOST_FOREACH宏之后,我花了几个小时试图找出如何将宏控件设置为作用域。在解决这个问题的过程中,我偶然发现了这个问题,希望它能给出答案!但是,不完全是这样。所以,我通读了所有的文章和原文。然后我觉得有点傻。。。宏本质上是将代码直接插入其所在的位置。这意味着我们可以有一个宏:
#define LOOP_3() \
for(int i = 0; i < 3; ++i)
让我们用那个混蛋
#define NEWSCOPE() \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(); sc.run; sc.run = 0)
...
NEWSCOPE()
std::cout << " In the Body!" << std::endl;
std::cout << "Not in body..." << std::endl;
...
/* === Output ===
Starting Scope!
In the Body!
Ending Scope!
Not in body...
*/
为了更好地使用ENCODED\u TYPE
(如何使BOOST\u FOREACH的设计变得非常简单!),允许SCOPE\u CONTROL
成为模板类型。在OpenSceneGraph中,这种事情经常使用Aronman的回答,但我不想显式调用startScope()和endScope()函数并消除用户忘记{}的可能性。如果所有代码都是为防止懒惰的程序员错误地使用库而设计的,这个星球会停下来。@radensb看看我更新的答案,如果没有任何点击,我想我会删除我的答案。我想你会让代码难以阅读和维护。从长远来看,这会伤害您或未来的员工,这是我正在做的事情,但是我必须在开始和结束时调用startScope和endScope()。我正在写一个库,希望它尽可能简单易用。使用宏可以强制一个新的作用域(我希望如此)并简化使用。@radensb这确实强制一个新的作用域,分配堆栈上的对象,它们将在这个作用域的末尾被释放,我不明白你怎么会希望有比这更简单的事情this@radensb我可能误解了您的问题,因为我不知道startscope
和endscope
函数的作用,但事实是,在c++@radensb中不应该真正使用宏,也许在API中使用术语“scope”会产生误导。也许有更好的名称,以避免与“范围”的正常含义混淆。这似乎仍然是RAII的工作。“setup”和“cleanup”分别是构造函数和析构函数的目的。如果你的构造函数和析构函数真的在做他们的工作,你可以说像{MyClass myClassInstance;/*在这里做你的事情*/}
,它会像你试图做的那样被清理干净。这与我想的非常接近,但如果可能的话,我希望看起来像我的第二个例子。如果没有,这可能会奏效。我已经研究了一段时间的宏技巧,其中一些真的很有创意。我希望有som
class SCOPE_CONTROL {
public:
SCOPE_CONTROL(MyClass myClassInstance): control(myClassInstance), run(1) {
control.setup();
}
~SCOPE_CONTROL() { control.cleanup(); }
bool run;
MyClass & control;
}
#define NEWSCOPE(control) \
for(SCOPE_CONTROL sc = SCOPE_CONTROL(control); sc.run; sc.run = 0)
...
NEWSCOPE(myClassInstance)
{
// CREATE LOCAL VARS
// DO STUFF IN THIS SCOPE
} // end scope, destroy locals
...