与lambda尾随返回类型不一致
Inconsistency with lambda trailing return types
考虑使用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)
在lambda2
应该只是decltype(id == 10)
的缩写形式,但实际上它不是,那么原因是什么呢?
这是GCC中的一个bug吗?
通过将表达式放入返回类型中,您允许编译器调用SFINAE。这意味着,如果id == 10
不是模板替换后的合法表达式,则不会导致编译错误。这允许is_detected
判断该表达式是否合法,并根据判断返回一个值。
但是SFINAE只作用于函数的签名。对于第二种情况,签名是decltype(auto)
。SFINAE无法进入函数将返回表达式拉入签名中。因此,如果你试图用一个id == 10
不合法的类型实例化这个函数,这只会在函数实例化时被捕获。到那时,SFINAE已经来不及保护你了。
decltype(auto)
与decltype(expression)
不相同。它们很相似,但不完全相同。
标准规定:
函数模板可以使用返回类型演绎。这个推论需要放置在实例化处,即使表达式在返回语句中不是依赖的。此实例化不在立即上下文中
所以在GCC中没有bug,它遵循标准,lambda1
是而不是等同于lambda2
。
相关文章:
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 在 C++(和 C)中进行类型转换时明显不一致
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 从 C++ 函数与 Python 函数返回的不一致值用于偏斜正态分布
- 为什么函数的返回类型与实际句子不一致?
- 返回类型不可知模板类成员功能
- 返回类型不正确
- 自动返回类型不推断引用
- 本地类规则是否与c++14返回类型推导一致
- lambda函数返回类型不起作用
- 具有返回类型的函数模板,该返回类型不能从参数中推导出来
- 函数声明和定义的返回类型不匹配,编译器可以吗?
- 当返回类型不是指针时返回NULL
- c++中的字符串返回类型不返回输出
- 具有基类的CRTP试图获取派生类成员的返回类型:不完整类型的使用无效
- 与lambda尾随返回类型不一致
- 虚函数与它覆盖的函数的返回类型不协变
- 返回类型不匹配(或不匹配)
- 调用返回类型不完整的方法和无法解释的模板解决方案
- 枚举返回类型不起作用 C [错误 C2440]