考虑使用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>;其中ResultOfT只是std::result_of的包装器。
为什么lambda1和lambda2在这个意义上不是等价的?
根据我的理解,decltype(auto) at lambda2应该只是decltype(id == 10)的简短形式,但实际上并非如此,那么原因是什么呢?
这是GCC的错误吗?
发布于 2016-11-08 14:43:42
标准他说
函数模板可以使用返回类型推断。即使返回语句中的表达式不依赖,也会在实例化时进行扣减。这个实例化不是在SFINAE.的直接上下文中进行的。
所以GCC身上没有什么问题,它遵循了标准,lambda1是,而不是,相当于lambda2。
发布于 2016-11-02 20:14:47
通过将表达式放入返回类型,允许编译器调用SFINAE。这意味着,如果id == 10不是模板替换后的合法表达式,那么编译错误就不会产生。这允许is_detected确定该表达式是否合法,因此返回基于该确定的值。
但是SFINAE只对函数的签名起作用。对于第二种情况,签名是decltype(auto)。SFINAE无法将返回表达式拉到签名中。因此,如果尝试用id == 10不合法的类型实例化此函数,则只有在实例化该函数时才会捕获该函数。到那时,对SFINAE来说保护你已经太迟了。
decltype(auto)与decltype(expression)不完全相同。它们是相似的,但并不完全相同。
https://stackoverflow.com/questions/40387970
复制相似问题