如果给出显式 return 类型,则从函数返回通用 lambda 表达式会导致编译器警告

Returning a generic lambda expression from a function causes compiler warnings if an explicit return type is given

我有一个函数,其 return 类型是一个简单的通用 lambda 表达式。 (由这个函数编辑的 lambda return 最终作为参数传递给像 std::transform()std::accumulate() 这样的 STL 算法。)

当 lambda 没有明确的 return 类型时,编译器不会发出警告:

inline auto AccumulateInto() {
    return [](const auto& src, const auto& dst) {return dst + src; };
}

当 lambda 具有明确的 return 指定类型时:

inline auto AccumulateInto() {
    return [](const auto& src, const auto& dst) -> decltype(dst) {return dst + src; };
}

两个编译器发出这些类似的警告:

GCC: returning 引用临时 [-Wreturn-local-addr]

MSVC: return局部变量或临时变量的地址

是否应该注意此警告,因为它表明该方法存在缺陷(可能存在未定义的行为!)并且应该进行重构?或者它们是“噪音”?

我无法确定为什么显式指定 return 类型会导致 returned 表达式成为“临时”,否则它不会。请解释,谢谢!

编辑(添加更多上下文):

希望对 lambda 使用 auto 参数是因为 srcdst 可能是不同的类型(例如,一个是 std::uint8_t,一个是 std::uint_16t),但我希望 return 始终与 dst 参数的类型相同,而不管 src.

的类型如何

重点是 decltype(dst)auto const &(您可以在其中看到 auto 作为模板类型`,因此 lambda return a reference(我重复:reference)常量对象。

问题是引用

dst + src

即:对临时值的引用,从操作 dst + src 创建的临时对象,当 lambda 结束执行时,它不再存在。

一个可能的解决方案:删除 -> decltype(dst) 或将其更改为 -> decltype(dst+src),这样您 return 一个值,而不是一个引用。

另一种方法(在这种情况下需要更多的打字,但在更复杂的情况下可能更可取)可以从 decltype() 编辑的类型 return 中删除引用部分。

所以

-> std::remove_reference_t<decltype(dst)>

或者,按照 Jarod42 的建议,也

-> std::decay_t<decltype(dst)>

如果dst的类型支持一元运算符+(return与dst的类型相同),另一种简单的解决方案可以是

-> decltype(+dst)

这样,+dst 是一个表达式,而不是变量,所以 decltype(+dst) 不再是引用。