使用 C++变量初始化期间的 lambda 函数

发布于 2024-09-13 20:34:02 字数 1119 浏览 1 评论 0原文

我想你们中的许多人在某个地方都有这种代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傲性难收 2024-09-20 20:34:02

这是其他语言中相当常见的技术。几乎Scheme 的每个高级功能都是根据立即调用的lambda 来定义的。

在JavaScript中,它是“模块模式”的基础,例如

var myModule = (function() {

    // declare variables and functions (which will be "private")

    return {
       // populate this object literal with "public" functions
    };

})();

,声明并立即调用匿名函数,从而隐藏任何内部细节,仅将返回值暴露在外部。

唯一的缺点是,在随意阅读代码时,return 语句看起来像是从外部函数返回(在 Java lambda 战争期间对此存在激烈争议)。但是,一旦你的语言有了 lambda 表达式,你就必须习惯这一点。

像 C++ 这样的命令式语言有许多语言特性,它们会受益于能够返回值(而不是像 void 函数)。例如,if 有一个替代方案,即三元运算符 expr ? a:b

在 Ruby 中,几乎所有语句都可以被计算,因此不需要可以提供返回值的单独语法。如果 C++ 以这种方式工作,这将意味着:

auto result = try
{
    getIntegerSomehow();
}
catch (const SomeException &)
{
    0;
}

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.

var myModule = (function() {

    // declare variables and functions (which will be "private")

    return {
       // populate this object literal with "public" functions
    };

})();

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 operator expr ? 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:

auto result = try
{
    getIntegerSomehow();
}
catch (const SomeException &)
{
    0;
}
最初的梦 2024-09-20 20:34:02

在这种情况下,我根本看不出有任何理由使用开关盒。任何像样的编译器都会使用 if 语句生成与使用 switch case 一样快的代码。

if(bar == SOMETHING)
   foo = 5;
else if(bar == STHNELSE)
   foo = 10;

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.

if(bar == SOMETHING)
   foo = 5;
else if(bar == STHNELSE)
   foo = 10;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文