【问题标题】:Returning a generic lambda expression from a function causes compiler warnings if an explicit return type is given如果给出显式返回类型,则从函数返回泛型 lambda 表达式会导致编译器警告
【发布时间】:2021-03-13 21:26:12
【问题描述】:

我有一个函数,它的返回类型是一个简单的通用 lambda 表达式。 (此函数返回的 lambda 最终会作为参数传递给 std::transform()std::accumulate() 等 STL 算法。)

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

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

当 lambda 明确指定返回类型时:

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

两个编译器都会发出类似的警告:

GCC:返回对临时 [-Wreturn-local-addr] 的引用

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

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

我无法确定为什么显式指定返回类型会导致返回的表达式是“临时的”,而如果不是这样的话。请解释一下,谢谢!

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

对 lambda 使用 auto 参数的愿望是 srcdst 可能是不同的类型(例如,一个是 std::uint8_t,一个是 std::uint_16t),但我希望返回 ALWAYS与dst 参数的类型相同,与src 的类型无关。

【问题讨论】:

标签: c++ gcc visual-c++ c++14 generic-lambda


【解决方案1】:

重点是 decltype(dst)auto const & (您可以将 auto 视为模板类型`,因此 lambda 返回一个 reference(我重复一遍:一个 reference ) 到一个常量对象。

问题在于这是对

的引用
dst + src

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

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

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

所以

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

或者,按照 Jarod42 的建议,也

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

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

-> decltype(+dst)

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

【讨论】:

  • std::decay_t 可能是另一种选择(取决于 OP 的需要)。
  • @Jarod42 - 右:总和的decltype() 是一个可能的解决方案,而不是解决方案。答案改进以强调这一点。
  • 谢谢 max66 和 Jarod42。我在原始帖子中添加了一些额外的上下文。
  • @Jarod42 - 哦!我必须多睡。谢谢。
  • 编译器警告并不具体,所以我认为封闭的 AccumulateInto() 函数的返回是有问题的,但从你的解释看来,它实际上是封闭的 lambda 表达式的返回类型,即有问题...这是正确的吗?
猜你喜欢
  • 2022-12-13
  • 1970-01-01
  • 2021-01-31
  • 2014-08-06
  • 2015-06-19
  • 2012-03-26
  • 2023-02-16
  • 2016-08-14
  • 1970-01-01
相关资源
最近更新 更多