使用 C++变量初始化期间的 lambda 函数
我想你们中的许多人在某个地方都有这种代码:
int foo;
switch (bar) {
case SOMETHING: foo = 5; break;
case STHNELSE: foo = 10; break;
...
}
但是这个代码有一些缺点:
- 你很容易忘记一个“break”
foo
变量不是const,而它应该是const- 它只是不漂亮
所以我开始想知道是否有办法“改进”这种代码,我得到了这个小想法:
const int foo = [&]() -> int {
switch (bar) {
case SOMETHING: return 5;
case STHNELSE: return 10;
...
}
}();
注意:第一对括号不是强制性的,但 MSVC++ 还不支持这一点
可以对 if-else 使用相同的技巧,其中三元运算符太复杂,需要通过指针传递才能初始化的变量(例如 DirectX 函数)等。
我的问题是:
- 这段代码有什么问题吗?我没看到?
- 你觉得它比上面那个更好吗?
- g++ 似乎内联了函数,但是你认为所有编译器都会这样做吗?
编辑:这就是我所说的“DirectX 函数”的意思
_xAudio2 = [&]() -> std::shared_ptr<IXAudio2> {
IXAudio2* ptr = nullptr;
if (FAILED(XAudio2Create(&ptr, xAudioFlags, XAUDIO2_DEFAULT_PROCESSOR)))
throw std::runtime_error("XAudio2Create failed");
return std::shared_ptr<IXAudio2>(ptr, [](IUnknown* ptr) { ptr->Release(); });
}();
I think many of you have this kind of code somewhere:
int foo;
switch (bar) {
case SOMETHING: foo = 5; break;
case STHNELSE: foo = 10; break;
...
}
But this code has some drawbacks:
- You can easily forget a "break"
- The
foo
variable is not const while it should be - It's just not beautiful
So I started wondering if there was a way to "improve" this kind of code, and I got this little idea:
const int foo = [&]() -> int {
switch (bar) {
case SOMETHING: return 5;
case STHNELSE: return 10;
...
}
}();
Note: the first pair of parentheses it not mandatory, but MSVC++ doesn't support this yet
You can use the same trick with if-else where the ternary operator would be too complicated, variables that require to be passed by pointers to be initialized (like for DirectX functions), etc.
My questions are:
- Is there anything wrong with this code that I didn't see?
- Do you find it better than the one above?
- g++ seems to inline the function, but do you think that all compilers will do so?
EDIT: this is what I mean by "DirectX functions"
_xAudio2 = [&]() -> std::shared_ptr<IXAudio2> {
IXAudio2* ptr = nullptr;
if (FAILED(XAudio2Create(&ptr, xAudioFlags, XAUDIO2_DEFAULT_PROCESSOR)))
throw std::runtime_error("XAudio2Create failed");
return std::shared_ptr<IXAudio2>(ptr, [](IUnknown* ptr) { ptr->Release(); });
}();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是其他语言中相当常见的技术。几乎Scheme 的每个高级功能都是根据立即调用的lambda 来定义的。
在JavaScript中,它是“模块模式”的基础,例如
,声明并立即调用匿名函数,从而隐藏任何内部细节,仅将返回值暴露在外部。
唯一的缺点是,在随意阅读代码时,
return
语句看起来像是从外部函数返回(在 Java lambda 战争期间对此存在激烈争议)。但是,一旦你的语言有了 lambda 表达式,你就必须习惯这一点。像 C++ 这样的命令式语言有许多语言特性,它们会受益于能够返回值(而不是像
void
函数)。例如,if
有一个替代方案,即三元运算符expr ? a:b
。在 Ruby 中,几乎所有语句都可以被计算,因此不需要可以提供返回值的单独语法。如果 C++ 以这种方式工作,这将意味着:
This is a fairly common technique in other languages. Almost every high-level feature of Scheme is defined in terms of lambdas that are immediately called.
In JavaScript it is the basis of the "module pattern", e.g.
So an anonymous function is declared and immediately called, so that any internal details are hidden and only the return value is exposed externally.
The only downsides is that on a casual reading of the code, the
return
statements will appear to be returning from the outer function (there was intense controversy about this during the Java lambda wars). But this is just something you have to get used to once your language has lambdas.There are many language features in an imperative language like C++ which would benefit from being able to return a value (rather than being like a
void
function). For example,if
has an alternative, the tertiary operatorexpr ? a : b
.In Ruby pretty much all statements can be evaluated, so there is no need for a separate syntax where a return value can be supplied. If C++ worked that way, this would mean things like:
在这种情况下,我根本看不出有任何理由使用开关盒。任何像样的编译器都会使用 if 语句生成与使用 switch case 一样快的代码。
I don't see any reason at all to use a switch case in such a case. Any decent compiler will generate just as fast code with if statements as with a switch case.