【问题标题】:Why does std::result_of not work with lambdas?为什么 std::result_of 不适用于 lambda?
【发布时间】:2015-04-21 12:43:47
【问题描述】:

我设法将我的案例简化为以下最简单的代码:

#include <type_traits>

auto call(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
  return f();
}

int main()
{
  return call([] { return 0; });
}

gcc-4.9.2 和 gcc-5.0.0 都不编译!

两者都认为“调用”应该返回一个 lambda 函数! 不知道“调用”返回一个整数。

这是编译器中的错误还是我的 c++ 关闭? 非常感谢。

【问题讨论】:

  • 这不是你称呼std::result_of的方式,应该是typename std::result_of&lt;decltype(f)()&gt;::type。或者更简单,你可以写decltype(f())
  • @Paul 这看起来是对的,如果作为答案发布会更好。你打算这样做吗?
  • 在 gcc 4.9 中,auto 被允许作为参数。见here
  • @Paul 不过,它并没有按照文档的方式实现。众所周知,它有缺陷。
  • @hvd 现在,the buggy implementation 实际上忽略了尾随返回类型,并将占位符 auto 也转换为 T

标签: c++ c++11 gcc lambda


【解决方案1】:

您的代码不是有效的 C++,因为函数参数类型不能是 auto,此语法已针对 Concepts Lite 提出,将来可能会成为该语言的一部分。

result_of 需要一个调用表达式,它将从中推断出返回类型。

解决这两个问题,您的代码就变成了

template<typename F>
auto call(F const& f) -> typename std::result_of<decltype(f)()>::type
//                    or typename std::result_of<F()>::type
{
  return f();
}

或者你可以使用

template<typename F>
auto call(F const& f) -> decltype(f())
{
  return f();
}

Live demo


我认为如果你修复了result_of 表达式,你的原始代码应该可以编译,但它不会在 gcc-4.9 或 5.0 上;也许这是 gcc 扩展的一个错误,它允许参数类型为 auto

// This fails to compile
auto call3(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
  return f();
}

【讨论】:

  • 请参阅帖子主题中@T.C. 的讨论。他指出 gcc 中允许使用 auto 参数,但错误的实现可能会搞砸这种情况。
  • @user2059893 这完全符合关于 无法转换为 int 的错误消息
  • 没错。看来我们可能不得不等待更高的编译器版本(5.0.0 不会编译它),或者干脆避免使用非标准的自动参数。非常感谢您的解释。
【解决方案2】:

这不是你称呼std::result_of的方式,应该是:

auto call(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
  return f();
}

或者更简单的你可以写:

auto call(const auto& f) -> decltype(f())
{
  return f();
}

【讨论】:

  • 谢谢。你是绝对正确的。这是一个较小的问题,更大的问题似乎是 gcc 的自动参数实现有问题。感谢您的澄清。
【解决方案3】:

自 c++14 / c++1y 起支持 FUNCTION PARAMETER AS 'auto'

这里的问题是两个汽车都将被视为同一类型[由语言标准决定 - 讨厌的人会说错误]。

解决方案:

1) '->' 和返回类型从 c++14 开始根本不需要,因为函数调用只有一个返回语句。

2) 为了克服所有汽车的相同类型的策略 [auto:1, auto:2,...], LETS GO VARIADIC

3) 是否显式检查单个参数。

#include <initializer_list>

auto call(const auto&... f)
{
    static_assert(sizeof...(f)==1,"Exactly 1 argument should be provided");
    return std::begin({f...})[0]();   // black magic : to call first arg of singleton pack
}


int main()
{
    return call([] {return 0;});
}

希望它能解决您的问题。 注意:在 TDM GCC 4.9.2、cygwin gcc 5.0 中测试

应该与 -std=c++14 或 -std=c++1y 一起编译

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多