Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make lambdas work with std::nullopt

Background

I have a series of lambdas that perform different checks on the captured variables and return std::nullopt if the check failed. return std::nullopt is the first return statement. Then, if the check succeeded, they go on and compute the value.

Problem

The types of return expressions are not consistent, e.g. std::nullopt_t cannot be converted to std::optional<T>, even though the other way around works. In particular, I'd like the following code to compile and run, printing 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.

Thoughts

I believe that I need to use std::common_type<Args...> somewhere, but I can neither enforce presence of it or deduce Args, as it might require language support.

like image 923
Incomputable Avatar asked Mar 07 '23 02:03

Incomputable


1 Answers

Instead of using template type deduction to infer the return type of the lambda, why not explicitly specify that return type?

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

    return 2;
};

std::common_type is commonly with templates, which you don't have.

like image 197
Rakete1111 Avatar answered Mar 16 '23 18:03

Rakete1111