【问题标题】:How to make lambdas work with std::nullopt如何使 lambdas 与 std::nullopt 一起使用
【发布时间】:2018-11-10 05:23:58
【问题描述】:

背景

我有一系列 lambda,它们对捕获的变量执行不同的检查,如果检查失败,则返回 std::nulloptreturn std::nullopt 是第一个返回语句。然后,如果检查成功,他们继续计算值。

问题

返回表达式的类型不一致,例如std::nullopt_t 不能转换为 std::optional<T>,即使反过来也可以。特别是,我想编译和运行以下代码,打印 2:

#include <functional>
#include <utility>
#include <optional>

int x = 3;

auto lambda = [](){
    if (x == 2)
        return std::nullopt;

    return std::optional(2);
};

#include <iostream>

int main () {
    using return_type = std::invoke_result_t<decltype(lambda)>;
    static_assert(std::is_same<return_type, std::optional<int>>{}, 
                  "return type is still std::nullopt_t");

    std::cout << lambda().value() << '\n';
}

Wandbox Demo.

想法

我认为我需要在某处使用std::common_type&lt;Args...&gt;,但我既不能强制它的存在也不能推断Args,因为它可能需要语言支持。

【问题讨论】:

  • std::optional&lt;int&gt; result{}; if(2 != x) { result.emplace(2); } return result;
  • @VTT,哇,我没想到。这样会好一些。

标签: c++ lambda c++17 return-type-deduction


【解决方案1】:

与其使用模板类型推导来推断 lambda 的返回类型,为什么不明确指定该返回类型?

auto lambda = []() -> std::optional<int> {
    if (x == 2)
        return std::nullopt;

    return 2;
};

std::common_type 通常带有模板,而您没有。

【讨论】:

  • 有没有办法自动插入std::common_type?我相信这将是对语言的一个很好的改变,但我不确定是否会出现问题。
  • @Incomputable 我认为委员会是故意反对的。并且有充分的理由海事组织;我们也不允许模板参数推导中的类型不匹配,我们也不应该在这里。
  • @BaummitAugen 他们可以应用运算符?: 的规则。我理解在模板参数推导中禁止类型不匹配背后的基本原理,但在这里我真的很想看到放弃这个选项的原始讨论(如果有的话);)
  • @Holt 我发现?: 规则对于它的作用来说太复杂了。一点也不赞成。
  • @PasserBy 我发现很多 C++ 规则对于它们的作用来说太复杂了,但我明白你的意思。 ;) 无论实际规则如何,我认为应该允许从多个 return 语句中扣除返回类型(可能使用保守规则)。
【解决方案2】:

我建议坚持使用单个 return 语句并明确指定结果类型,而不使用 nullopt。当函数返回整数或 nullopt 时,它看起来有些误导。特别是如果函数更长。此外,如果值类型具有显式构造函数,则使用 emplace 可以避免再次键入值类型名称。

auto lambda = []()
{
    std::optional<int> result{};
    if(2 != x)
    {
        result.emplace(2);
    }
    return result;
};

【讨论】:

  • @Incomputable 事实证明它比我想象的还要误导......
  • 如果你有一个很长的 lambda 你做错了什么:)
猜你喜欢
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多