使用C++宏创建新作用域

Creating a new scope with a C++ Macro?

本文关键字:作用域 创建 C++ 使用      更新时间:2023-10-16

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

比方说,我的类中有两个成员函数,setup()和cleanup(),其中setup(。

目前,我这样做:

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

所以你不需要宏

听起来startScopeendScope实际上应该是构造函数和析构函数,但再一次,如果不知道它们实际做了什么,就很难知道

更新:我试图给你一个答案,但我只是咆哮。

类似于构造函数和析构函数概念

对我来说,这听起来像是构造函数和析构函数,当构造函数和析构函数进行设置和清理时,操作将使用RAII自然且可读地执行。

还有一件事,你说你的第一个解决方案(我有点意外地还给了你)正在发挥作用,为什么需要用C中的宏来模拟C++提供的功能(如模板和对象)。对于几乎所有的情况,尤其是C++11,宏只会让事情变得更糟、更难调试,而且在您的情况下,似乎在执行宏时实际上必须键入更多?

我的建议是重新思考为什么需要一个宏,以及为什么setupcleanup不能是构造函数和析构函数。

您可以像使用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)

就我个人而言,我更喜欢尽可能远离宏。

在看到BOOST_FOREACH宏后,我花了几个小时试图弄清楚如何使宏控件成为作用域。在弄清楚的过程中,我遇到了这个问题,希望它能给出答案!但是,不完全是这样。因此,我通读了BOOST_FOREACH的所有代码和BOOST_for EACH的原始设计。然后我觉得有点笨。。。宏本质上是将代码直接插入代码所在的位置。这意味着我们可以有一个宏:

#define LOOP_3() 
    for(int i = 0; i < 3; ++i)

现在,让我们来测试一下!

LOOP_3() std::cout << "Hello World!" << std::endl;
/* === Output ===
Hello World!
Hello World!
Hello World!
*/

耶!但是,这怎么有用呢?那么,在循环的最后,i会发生什么?调用了析构函数,这对于i来说并不太花哨,但这个想法是存在的。

我们现在只需要一个类来处理这个问题:

class SCOPE_CONTROL {
public:
    SCOPE_CONTROL(): run(1) { std::cout << "Starting Scope!" << std::endl; }
    ~SCOPE_CONTROL() { std::cout << "Ending Scope!" << std::endl; }
    bool run;
}

让我们用那个笨蛋吧!

#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...
*/

要使用setupcleanup函数,只需更改一点点即可!

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

为了更好地使用ENCODED_TYPE(如何在BOOST_FOREACH的设计中变得非常简单!)允许SCOPE_CONTROL作为模板类型。

将整个范围放在宏替换中的一个更好的选择是使用类似finally块的东西。我已经成功地用这些宏封装了链接的解决方案:

#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 );

用法:

{
    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.)
}

这是异常安全的,并且cleanupsetup成功完成时执行,就像构造函数/析构函数对一样。但是cleanup不能抛出异常。


但如果你想用老式的方式…

您可以通过使用可变宏将整个范围包含在宏中:

#define NEWSCOPE( INSTANCE, ... ) { 
    (INSTANCE).setup(); /* call the setup function */ 
    { __VA_ARGS__ } /* paste teh codez here */ 
    (INSTANCE).cleanup(); /* call the cleanup function */

我建议不要将cleanup放在内部作用域内,因为作用域的目的是包含声明和名称,但您希望从外部作用域使用INSTANCE的名称。

用法:

NEWSCOPE ( myClassInstance,
    // Do stuff.
    // Multiple declarations, anything can go here as if inside braces.
    // (But no #define directives. Down, boy.)
)