Как заставить лямбды работать с std :: nullopt - PullRequest
0 голосов
/ 31 мая 2018

Фон

У меня есть ряд лямбд, которые выполняют различные проверки перехваченных переменных и возвращают std::nullopt, если проверка не удалась.return 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 .

Мысли

IПолагайте, что мне нужно где-то использовать std::common_type<Args...>, но я не могу ни навязать его наличие, ни вывести Args, так как это может потребовать языковой поддержки.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Я предлагаю придерживаться одного оператора возврата и явно заданного типа результата без использования nullopt.Это выглядит несколько вводящим в заблуждение, когда функция возвращает целое число или nullopt.Особенно если функция была длиннее.Также, если тип значения был чем-то с явным конструктором, тогда использование emplace позволяет избежать повторного ввода имени типа значения.

auto lambda = []()
{
    std::optional<int> result{};
    if(2 != x)
    {
        result.emplace(2);
    }
    return result;
};
0 голосов
/ 31 мая 2018

Вместо использования вывода типа шаблона для вывода типа возврата лямбды, почему бы не указать явно этот тип возврата?

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

    return 2;
};

std::common_type обычно с шаблонами, которых у вас нет.

...