[英]Can I get return type auto to work with lambdas of the same signature but different captures?
我正在尝试使用 auto 作为返回的 lambda function 的返回类型。 这是一个最小的示例,它演示了我遇到的问题:
#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;
}
在我的 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.
对,它们都被推断为lambda
。 而且它们都具有相同的void(void)
签名。 我看到问题是因为它们指定了不同的捕获吗? 如果是这样,我有什么选择来获得相同的 function 调用以使调用者工作(如main
中的cout
调用中所示)。
我看到问题是因为它们指定了不同的捕获吗?
即使它们完全一样,你也会看到一个问题,一个令牌一个令牌。
每个 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;
};
}
而且它们都具有相同的
void(void)
签名。
虽然 lambda 具有相同的operator()
签名,但它们不是相同的 class 类型。 它们是具有不同类型的不同对象。 自动返回类型推导要求所有返回语句具有相同的类型,而您在这里没有。
在这种情况下,您有不同的类型,您需要一个共同的返回类型。 您可以使用std::function
获得它,因为它允许您通过operator()
类型而不是 lambda 类型返回。 那给你
std::function<void(void)> get_func()
{
auto i = std::make_unique<int>(2);
if (*i == 1) {
return [i=std::move(i)]() {
return *i;
};
}
return [](){ return 2; };
}
我认为最好的变体(预示双关语)是 StoryTeller 将逻辑放入单个 lambda 的解决方案。
为了好玩,作为替代方案,您可以使用一个变体来固定您的 lambda。 您可以围绕它创建一个简单的包装器:
template <class... Fs>
struct Lambda_fixed_variant
{
std::variant<Fs...> f_;
template <class L>
// requires std::is_constructible_v<decltype(f_), std::in_place_type_t<L>, L&&>
Lambda_fixed_variant(L l)
: f_{std::in_place_type_t<L>{}, std::move(l)}
{}
template <class... Args>
auto operator()(Args&&... args) const
{
return std::visit([&] (const auto& l) {
return l(std::forward<Args>(args)...);
},
f_
);
}
};
auto get_func()
{
auto i = std::make_unique<int>(2);
auto l1 = [i=std::move(i)]() { return *i; };
auto l2 = [](){ return 2; };
using L1 = decltype(l1);
using L2 = decltype(l2);
if (true)
{
return Lambda_fixed_variant<L1, L2>{std::move(l1)};
}
return Lambda_fixed_variant<L1, L2>{l2};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.