与 lambda 尾随 return 类型不一致
Inconsistency with lambda trailing return types
考虑使用 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
的包装器。
为什么 lambda1
和 lambda2
在这个意义上不等价?
据我理解lambda2
处的decltype(auto)
应该只是decltype(id == 10)
的缩写形式,但实际上不是,这是什么原因?
这是 GCC 中的错误吗?
通过将表达式放入 return 类型,您允许编译器调用 SFINAE。这意味着如果 id == 10
在模板替换后不是合法表达式,则不会导致编译错误。这允许 is_detected
确定这是否是一个合法的表达式,因此 return 一个基于该确定的值。
但 SFINAE 仅适用于函数的签名。而对于第二种情况,签名是decltype(auto)
。 SFINAE 无法进入将 return 表达式拉入签名的函数。因此,如果您尝试使用 id == 10
不合法的类型来实例化此函数,则只有在实例化该函数时才会被捕获。到那时,SFINAE 保护你已经来不及了。
decltype(auto)
与 decltype(expression)
不同。它们相似,但不完全相同。
标准says:
Function templates can use return type deduction. The deduction takes
place at instantiation even if the expression in the return statement
is not dependent. This instantiation is not in an immediate context
for the purposes of SFINAE.
因此 GCC 中没有错误,它遵循标准并且 lambda1
NOT 等同于 lambda2
.
考虑使用 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
的包装器。
为什么 lambda1
和 lambda2
在这个意义上不等价?
据我理解lambda2
处的decltype(auto)
应该只是decltype(id == 10)
的缩写形式,但实际上不是,这是什么原因?
这是 GCC 中的错误吗?
通过将表达式放入 return 类型,您允许编译器调用 SFINAE。这意味着如果 id == 10
在模板替换后不是合法表达式,则不会导致编译错误。这允许 is_detected
确定这是否是一个合法的表达式,因此 return 一个基于该确定的值。
但 SFINAE 仅适用于函数的签名。而对于第二种情况,签名是decltype(auto)
。 SFINAE 无法进入将 return 表达式拉入签名的函数。因此,如果您尝试使用 id == 10
不合法的类型来实例化此函数,则只有在实例化该函数时才会被捕获。到那时,SFINAE 保护你已经来不及了。
decltype(auto)
与 decltype(expression)
不同。它们相似,但不完全相同。
标准says:
Function templates can use return type deduction. The deduction takes place at instantiation even if the expression in the return statement is not dependent. This instantiation is not in an immediate context for the purposes of SFINAE.
因此 GCC 中没有错误,它遵循标准并且 lambda1
NOT 等同于 lambda2
.