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

Vah*_*agn 1 c++ gcc decltype trailing-return-type c++17

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

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>;
Run Code Online (Sandbox Code Playgroud)

哪里ResultOfT只是一个包装std::result_of.

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

按我的理解decltype(auto),在lambda2应刚的缩写形式decltype(id == 10),但实际上它不是,那么是什么原因?

这是GCC中的错误吗?

Nic*_*las 5

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

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

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

  • 动机——不需要编译器编译模板函数体只是为了确定选择哪个重载——可能值得一提。 (2认同)