使用C++宏创建新作用域
Creating a new scope with a C++ Macro?
这可能吗?我想写一个宏,让它更容易使用我的一些类功能。
比方说,我的类中有两个成员函数,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
所以你不需要宏
听起来startScope
和endScope
实际上应该是构造函数和析构函数,但再一次,如果不知道它们实际做了什么,就很难知道
更新:我试图给你一个答案,但我只是咆哮。
类似于构造函数和析构函数概念
对我来说,这听起来像是构造函数和析构函数,当构造函数和析构函数进行设置和清理时,操作将使用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)
就我个人而言,我更喜欢尽可能远离宏。
在看到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...
*/
要使用setup
和cleanup
函数,只需更改一点点即可!
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.)
}
这是异常安全的,并且cleanup
在setup
成功完成时执行,就像构造函数/析构函数对一样。但是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.)
)
- 未在作用域中声明unordered_map
- 有没有一种方法可以在编译时获得作用域类名
- C++quit()函数中可能存在作用域问题
- 未在此作用域OpenCV3.4中声明cvSaveImage
- 全局作用域中函数指针的赋值
- 将非左值作为常量引用参数传递.临时是在本地作用域还是在调用方作用域中创建的?
- 用于创建新作用域的最佳C++宏
- 如何在 c++ 中创建一个可调试的文件作用域(静态?)类
- 使用C++宏创建新作用域
- 创建从外部作用域重新声明模板参数的typedef的负面影响
- 类方法中创建变量的作用域
- 如何使.h中创建的变量成为程序的全局作用域
- c++在文件级创建作用域
- c++作用域问题:创建一个矩阵类而不浪费空间
- CMAKE:在函数中创建和构建一个列表——使用目录或全局作用域
- 为结构的数组创建指针作用域和构造函数
- 在if语句if C++中创建对象时出现作用域问题
- 在作用域中创建指针时,当指针超出作用域时,指向的变量会发生什么情况
- 如何在实例和静态作用域之间创建成员变量
- c++对象正在创建同一数组的两个实例,但作用域不同