C++ 使用C+创建新范围+;宏?

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

这可能吗?我想写一个宏,使它更容易使用我的一些类的功能

假设我的类中有两个成员函数,setup()和cleanup(),其中setup()为需要在其自身范围内执行的某些操作设置参数,cleanup()执行清理(类似于构造函数和析构函数的概念)

目前,我这样做:

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
...