【问题标题】:Using C++ lambda functions during variable initialisation在变量初始化期间使用 C++ lambda 函数
【发布时间】:2010-08-09 23:59:49
【问题描述】:

我认为你们中的许多人在某处都有这种代码:

int foo;
switch (bar) {
  case SOMETHING: foo = 5;  break;
  case STHNELSE:  foo = 10; break;
  ...
}

但是这段代码有一些缺点:

  • 您很容易忘记“休息”
  • foo 变量不是 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(); });
}();

【问题讨论】:

  • 绝招!但无论如何,我会更进一步,将 lambda 转换为命名函数“int EnumToFoo(Enum)”:调用函数中的混乱更少,并自动使用描述性良好的名称进行记录;)。
  • 我支持 sjoerd - 我总是会重构任何映射函数 - 切换或其他方式
  • 在这种情况下,编写一个外部函数可能是值得的,但我不认为自己创建一个函数只是为了构建一个 DirectX 对象
  • Herb Sutter 的“Lambdas, Lambdas无处不在”演示文稿中介绍了这一点。 nwcpp.org/images/stories/lambda.pdf 第 32 页,顶部幻灯片。

标签: c++ lambda c++11


【解决方案1】:

这是其他语言中相当常见的技术。几乎所有 Scheme 的高级特性都是根据立即调用的 lambdas 定义的。

在 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;
}

【讨论】:

  • 谢谢,我不太习惯使用函数式语言
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2016-03-11
    • 2013-07-28
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2014-05-19
    • 1970-01-01
    相关资源
    最近更新 更多