如何使lambdas与std :: nullopt一起使用

时间:2018-05-31 08:46:37

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

背景

我有一系列lambdas对捕获的变量执行不同的检查,如果检查失败则返回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<Args...>,但我既不能强制执行也不能推断Args,因为它可能需要语言支持。

2 个答案:

答案 0 :(得分:5)

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

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

    return 2;
};

std::common_type通常包含您没有的模板。

答案 1 :(得分:1)

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

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