C/C++宏/模板 blackmagic 生成唯一的名称
宏就好了。 模板很好。 几乎无论它起作用什么都很好。
例子是OpenGL;但该技术是 C++ 特定的,并且不依赖于 OpenGL 知识。
精确问题:
我想要一个表达式E;我不必指定唯一的名称;这样,在定义 E 的地方调用构造函数,在块 E 结束的地方调用析构函数。
例如,考虑:
class GlTranslate {
GLTranslate(float x, float y, float z); {
glPushMatrix();
glTranslatef(x, y, z);
}
~GlTranslate() { glPopMatrix(); }
};
手动解决方案:
{
GlTranslate foo(1.0, 0.0, 0.0); // I had to give it a name
.....
} // auto popmatrix
现在,我不仅有 glTranslate,还有许多其他 PushAttrib/PopAttrib 调用。我不想为每个变量起一个唯一的名称。是否有一些涉及宏模板的技巧......或者其他东西会自动创建一个变量,该变量的构造函数在定义时被调用;并在块末尾调用析构函数?
谢谢!
Macros are fine.
Templates are fine.
Pretty much whatever it works is fine.
The example is OpenGL; but the technique is C++ specific and relies on no knowledge of OpenGL.
Precise problem:
I want an expression E; where I do not have to specify a unique name; such that a constructor is called where E is defined, and a destructor is called where the block E is in ends.
For example, consider:
class GlTranslate {
GLTranslate(float x, float y, float z); {
glPushMatrix();
glTranslatef(x, y, z);
}
~GlTranslate() { glPopMatrix(); }
};
Manual solution:
{
GlTranslate foo(1.0, 0.0, 0.0); // I had to give it a name
.....
} // auto popmatrix
Now, I have this not only for glTranslate, but lots of other PushAttrib/PopAttrib calls too. I would prefer not to have to come up with a unique name for each var. Is there some trick involving macros templates ... or something else that will automatically create a variable who's constructor is called at point of definition; and destructor called at end of block?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我个人不会这样做,只是想出独特的名字。但如果你想这样做,一种方法是使用
if
和for
的组合:你可以这样使用它:
每个名称都在不同的范围内,并且不会'冲突。内部名称隐藏外部名称。
if
和for
循环中的表达式是常量,应该很容易被编译器优化。如果你确实想传递一个表达式,你可以使用 ScopedGuard 技巧(参见 最重要的
const
),但需要做更多的工作来编写它。但好的一面是,我们可以摆脱for
循环,并让我们的对象计算为false
:然后您提供正确的
enter
> 和leave
函数:现在您可以在用户端完全不使用名称来编写它:
如果您想一次传递多个表达式,则有点棘手,但您可以编写一个表达式模板作用于
运算符
,将所有表达式收集到scont
中。您需要从
scoped_obj
继承 RAII 对象,如下所示。所有这些都不涉及虚函数,并且涉及的函数对编译器是透明的。 ,通过将上面的 GLTranslate 更改为将单个整数添加到全局变量,并在离开时再次减去它,以及下面定义的 GLTranslateE ,我做了一个测试:
事实上 事实上,优化级别
-O2
的 GCC 输出如下:我没想到会这样,它优化得很好!
I would not do this personally but just come up with unique names. But if you want to do it, one way is to use a combination of
if
andfor
:You can use it like
Each of those names are in separate scopes and won't conflict. The inner names hide the outer names. The expressions in the
if
andfor
loops are constant and should be easily optimized by the compiler.If you really want to pass an expression, you can use the ScopedGuard trick (see Most Important
const
), but it will need some more work to write it. But the nice side is, that we can get rid of thefor
loop, and let our object evaluate tofalse
:You then provide the proper
enter
andleave
functions:Now you can write it entirely without a name on the user side:
If you want to pass multiple expressions at once, it's a bit more tricky, but you can write an expression template that acts on
operator,
to collect all expressions into ascont
.You need to inherit the RAII object from
scoped_obj<Class>
like the following showsAll of these involve no virtual functions, and the functions involved are transparent to the compiler. In fact, with the above
GLTranslate
changed to add a single integer to a global variable and when leaving subtracting it again, and the below definedGLTranslateE
, i did a test:In fact, GCC at optimization level
-O2
outputs this:I wouldn't have expected that, it optimized quite well!
如果您的编译器支持
__COUNTER__
(可能确实如此),您可以尝试:
If your compiler supports
__COUNTER__
(it probably does), you could try:For
我认为现在可以做这样的事情:
那么在代码中
显然需要C++11
I think it's now possible to do something like this:
then in the code
Obviously, C++11 is needed
使用 C++17,一个非常简单的宏,导致直观的用法:
并且可以嵌套:
Using C++17, a very simple macro leading to an intuitive usage:
And can be nested:
一个答案中描述的规范方法是使用 lambda 表达式作为块,在 C++ 中,您可以轻松编写模板函数
并像使用它一样
,但需要一种避免在作用域中定义名称的机制的最常见原因是长函数/ 可以做很多事情的方法。如果这种问题一直困扰着您,您可以尝试采用现代 OOP / 干净代码风格,使用非常短的方法/函数进行更改
The canonical way as described in one answer is to use a lambda expression as the block, in C++ you can easily write a template function
and use it like
but the most common reason for wanting a mechanism for avoiding defining names in your scope are long functions / methods that do lots of things. You might try a modern OOP / clean code inspired style with very short methods / functions for a change if this kind of problem keeps bothering you ????