使用有什么好处
template <typename L, typename R>
auto getsum(L l, R r) -> decltype(l + r) {return l + r;}
超过
template <typename L, typename R>
auto getsum(L l, R r) {return l + r;}
在模板实例化期间它不是编译成适当的类型吗?
使用有什么好处
template <typename L, typename R>
auto getsum(L l, R r) -> decltype(l + r) {return l + r;}
超过
template <typename L, typename R>
auto getsum(L l, R r) {return l + r;}
在模板实例化期间它不是编译成适当的类型吗?
使用[尾随返回类型语法]有什么好处?
一个可能的优势:尾随返回类型是 SFINAE 友好的。
只有在and之间存在加号运算符时,才会启用getsum()
具有尾随返回类型 ( )的函数。-> decltype( l + r )
l
r
如果你用几个不支持总和的参数调用它(例如,几个std::vector
's),你会得到一个不是错误的替换失败(SFINAE)。
getsum()
所以可以调用另一个函数。
以下是一个完整的编译示例,其中调用了“做一些不同的事情”版本getsum(a, b)
#include <vector>
template <typename ... Ts>
auto getsum (Ts...)
{ /* do something different */ }
template <typename L, typename R>
auto getsum (L l, R r) -> decltype( l + r )
{ return l + r; }
int main ()
{
std::vector<int> a, b;
getsum(a, b);
}
但是,如果您删除尾随返回类型
template <typename L, typename R>
auto getsum (L l, R r) // <<--- no more tailing return type!!!
{ return l + r; }
该代码不再编译,因为您没有替换失败而是硬错误。
一个优势显然是更短的代码。
但也有缺点:除了只能从 C++14 中获得自动返回类型推导外,还存在无法推导返回类型的情况。
假设函数的复杂度略有增加:
template <typename L, typename R>
auto getsum(L l, R r) {
if (l < 0)
return 0;
return l + r;
}
现在以下内容将无法编译:
int main() {
auto s = getsum(1L, 2); // error: inconsistent deduction for auto return type: 'int' and then 'long int'
}
我们通过显式指定返回类型来解决这个问题(例如,使用尾随返回类型语法):
auto getsum(L l, R r) -> decltype(l + r) {
if (l < 0)
return 0;
return l + r;
}
int main() {
auto s = getsum(1L, 2); // OK
}
您的第二个表达式可能与第一个表达式不同。decltype
有不同的扣除规则auto
。
要具有相同的返回类型,您必须这样写:
templtate <typename L, typename R>
auto getsum(L l, R r) -> decltype(auto) { return l + r; }
现在为了一个比另一个的优势
第二个片段的优点是不重复表达式。如果您有复杂的表达式,重复表达式可能会非常麻烦。
第一个版本的优点是编译器可以对返回类型中的表达式执行 SFINAE。
在 C++20 中,您可以只使用概念来正确约束函数:
auto getsum(arithmetic auto l, arithmetic auto r) {
return l + r;
}
由于 C++14,第二个只是第一个更简单的版本。在 C++14 之前,您可以将函数名称与auto
(所以这是关于代码样式)对齐。