c++ 11 带有 decltype 的尾随返回类型无法按预期工作
c++ 11 Trailing return type with decltype does not work as expected
为什么这"按预期"工作? 我的理解是这应该行不通:
template <class T, class U>
auto x(T a, U b) -> decltype(a<b ? a:b) {
return a > b ? a : b;
}
int main() {
cout << x<long, double>(1, 2.01) << endl;
cout << x<long, double>(5, 2.01) << endl;
}
我尝试了其他一些组合,例如:
template <class T, class U>
auto x(T a, U b) -> decltype(a<b ? a:a) {
return a > b ? a : b;
}
这样它就不会编译错误实际上第二个组合失败
了compile time error: Error C2440 'return': cannot convert from 'U' to 'T &'
这是意料之中的。我的理解是,第一个函数也应该失败并出现相同的错误,同时它工作正常。
?:
运算符的条件是什么并不重要。结果类型计算为第二和第三操作数的常见类型。下面是如何计算?:
运算符的通用类型和值类别的一部分,有关完整详细信息,请参阅 cppreference.com:
如果第二个和第三个操作数是同一类型的左值,则结果类型将是该类型的左值。
如果类型是不相关的左值,则有一些更复杂的规则来确定通用类型,但结果将是 prvalue,而不是 lvalue。特别是如果这两种类型是算术类型,如double
和long
,则应用通常的算术转换来获得公共类型。在long
和double
的情况下,该通用类型将double
。这与例如尝试添加两种不同的算术类型与+
时所做的类型计算相同,因此称为通常的算术转换。
因此,如果a
和b
具有相同的类型,则decltype(a<b ? a:b)
将是引用类型,否则它将不是引用类型。
这就是函数编译的原因。通用类型始终是这样,可以将两种输入类型转换为它。这也是为什么如果类型相等,函数具有未定义的行为,因为这样decltype
会给出一个引用,因此您将返回对其中一个函数参数的引用。
decltype(a<b ? a:a)
不适用于不同的类型,因为如上所述,a
和a
的常见类型是a
类型的参考。如果b
具有不同的不相关类型,则a > b ? a : b
的结果将是不能绑定到左值引用的 prvalue。
你可能会认为
template <class T, class U>
auto x(T a, U b) -> decltype(a < b ? a : b) {
return a > b ? a : b;
}
std::cout << x<long, double>(1, 2.01) << std::endl;
std::cout << x<long, double>(5, 2.01) << std::endl;
不会编译,因为尾随返回类型decltype(a < b ? a : b)
,即内部表达式a < b ? a : b
与返回表达式不同a > b ? a : b
但这是完全合法的,因为返回类型成为->
之后的任何类型。
现在,为什么下面的代码没有成功编译?
template <class T, class U>
auto x(T a, U b) -> decltype(a < b ? a : a) {
return a > b ? a : b;
}
std::cout << x<long, double>(1, 2.01) << std::endl;
std::cout << x<long, double>(5, 2.01) << std::endl;
这是因为您需要从尾随返回类型中删除引用,如下所示:
#include <type_traits>
template <class T, class U>
auto x(T a, U b) -> typename std::remove_reference<decltype(a < b ? a : a)>::type {
return (a > b ? a : b);
}
现在它编译成功。在这里查看
第二个示例之所以没有std::remove_reference
就无法编译,是因为作为三元运算符一部分的两种类型都是glvalue
s,这里说:
4( 如果 E2 和 E3 是相同类型和相同值的 gl值 类别,则结果具有相同的类型和值类别
所以a < b ? a : a
的结果是glvalue
.这就是您需要删除引用的原因。a < b ? a : b
的结果是一个prvalue
,因此,您无需删除引用。
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 函数作为模板参数,是否对返回类型强制约束
- C++中函数的向量返回类型引发错误
- 检查函数返回类型是否与STL容器类型值相同
- 为什么返回类型中需要typename?C++
- c++ 11 带有 decltype 的尾随返回类型无法按预期工作
- 虚函数如何工作,分配后新的返回类型会发生什么?
- 模板返回类型函数如何在C++中工作
- 模板占位符未在成员的返回类型中定义,仍然可以正常工作
- 将自动返回类型扣除工作为主要
- 尾随返回类型、声明和引用限定符:它们能一起工作吗?
- 为什么decltype返回类型在递归模板中失败,而返回类型演绎却工作得很好?
- SFINAE在返回类型中工作,但不作为模板参数
- 具有多重继承的协变返回类型.这些代码是如何工作的
- 与符号在函数声明的返回类型中是如何工作的