使用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
在这个意义上不相同?
根据我的理解,decltype(auto)
lambda2
应该只是decltype(id == 10)
的缩写形式,但事实上它并非如此,那么原因是什么?
这是GCC中的错误吗?
答案 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
。