我可以让返回类型自动处理具有相同签名但不同捕获的lambda吗?

fir*_*ush 2 c++ lambda auto c++17

我正在尝试使用auto作为返回的lambda函数的返回类型。这是一个最小的示例,它演示了我遇到的一个问题:

#include <iostream>
#include <memory>

auto
get_func()
{
    auto i = std::make_unique<int>(2);
    if (*i == 1) {
        return [i=std::move(i)]() {
            return *i;
        };
    }
    return [](){ return 2; };
}

int
main(int argc, char* argv[])
{
    auto func = get_func();
    std::cout << "val: " << func() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我的Mac上,出现以下编译错误:

$ g++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:13:5: error: 'auto' in return type deduced as '(lambda at test.cc:13:12)' here but deduced as '(lambda at test.cc:9:16)' in earlier return statement
    return [](){ return 2; };
    ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

是的,它们都推导为lambda。而且它们都具有相同的void(void)签名。我看到问题了吗,因为它们指定了不同的捕获?如果是这样,我有什么选择来获得相同的函数调用以使调用者正常工作(如中的cout调用所示main)。

Sto*_*ica 5

我看到问题了吗,因为它们指定了不同的捕获?

即使它们是完全相同的,您也会看到一个问题,一个又一个。

每个lambda表达式都会创建一个唯一的闭包类型,该闭包类型不同于任何其他lambda创建的任何闭包类型。无法解决这一差异,因此auto推论无法成功。

如果您打算返回两个不同的lambda(使用std::function,或者使用仅支持移动语义的自定义类型),则需要键入擦除实际函子。那,或者将整个逻辑汇总为一个lambda:

auto
get_func()
{
    auto i = std::make_unique<int>(2);
    return [i=std::move(i)]() {
        if (*i == 1) {
            return *i;
        }
        return 2;
    };
}
Run Code Online (Sandbox Code Playgroud)