与lambda尾随返​​回类型不一致

时间:2016-11-02 19:13:44

标签: c++ gcc c++17 decltype trailing-return-type

使用gcc-7.0.0最新快照考虑this代码:

auto lambda1 = [](auto&& id) -> decltype(id == 10) { return id == 10; };
auto lambda2 = [](auto&& id) -> decltype(auto)     { return id == 10; };

static_assert(!std::experimental::is_detected_v<ResultOfT,decltype(lambda1),std::string>);
//static_assert(!std::experimental::is_detected_v<ResultOfT,decltype(lambda2),std::string>);
// This doesn't even compile!?
auto bb = std::experimental::is_detected_v<ResultOfT,decltype(lambda2),std::string>;

其中ResultOfT只是std::result_of上的包装。

为什么lambda1lambda2在这个意义上不相同?

根据我的理解,decltype(auto) lambda2应该只是decltype(id == 10)的缩写形式,但事实上它并非如此,那么原因是什么?

这是GCC中的错误吗?

2 个答案:

答案 0 :(得分:5)

通过将表达式放在返回类型中,您允许编译器调用SFINAE。这意味着如果id == 10在模板替换后不是合法表达式,则不会产生编译错误。这允许is_detected确定这是否是合法表达,因此根据该决定返回值。

但SFINAE仅适用于该功能的签名。对于第二种情况,签名为decltype(auto)。 SFINAE无法达到将返回表达式拉入签名的功能。因此,如果尝试使用id == 10不合法的类型实例化此函数,则只有在实例化函数时才会捕获此函数。到那时,SFINAE保护你为时已晚。

decltype(auto)decltype(expression)不同。它们相似但不完全相同。

答案 1 :(得分:0)

标准says

  

函数模板可以使用返回类型推导。扣除需要   即使在return语句中的表达式,也在实例化时放置   不依赖。 此实例化不是直接上下文   就SFINAE而言。

因此GCC中没有错误,它遵循标准,lambda1 NOT 等同于lambda2