箭头语法在函数声明中的优点
Advantages of arrow syntax in function declaration
使用
有什么好处
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;}
模板实例化的时候没有编译成合适的类型吗?
自 C++14 以来,第二个只是第一个的更简单版本。
在 C++14 之前,您可以将函数名称与 auto
对齐(所以这是关于代码样式)。
一个明显的优势是代码更短。
但也有缺点:除了只能从 C++14 中使用自动 return 类型推导外,在某些情况下无法推导 return 类型。
假设函数的复杂度稍微增加:
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'
}
我们通过显式指定 return 类型来解决这个问题(例如,使用尾随 return 类型语法):
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
}
what are the advantages of using [trailing return type syntax] ?
一个可能的优势:尾随 return 类型是 SFINAE 友好的。
您的 getsum()
函数,尾随 return 类型 (-> 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);
}
但是如果你删除尾随 return 类型
template <typename L, typename R>
auto getsum (L l, R r) // <<--- no more tailing return type!!!
{ return l + r; }
代码不再编译,因为你没有替换失败,而是硬错误。
您的第二个表达式可能 return 与第一个不同。 decltype
的推导规则与 auto
不同。
要获得相同的 return 类型,您必须这样写:
templtate <typename L, typename R>
auto getsum(L l, R r) -> decltype(auto) { return l + r; }
现在来了解两者的优势
第二个片段的优点是不重复表达。如果您有复杂的表达式,重复表达式可能会非常麻烦。
第一个版本的优点是编译器可以对return类型的表达式执行SFINAE。
在 C++20 中,您可以只使用概念来适当地约束函数:
auto getsum(arithmetic auto l, arithmetic auto 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;}
模板实例化的时候没有编译成合适的类型吗?
自 C++14 以来,第二个只是第一个的更简单版本。
在 C++14 之前,您可以将函数名称与 auto
对齐(所以这是关于代码样式)。
一个明显的优势是代码更短。
但也有缺点:除了只能从 C++14 中使用自动 return 类型推导外,在某些情况下无法推导 return 类型。
假设函数的复杂度稍微增加:
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'
}
我们通过显式指定 return 类型来解决这个问题(例如,使用尾随 return 类型语法):
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
}
what are the advantages of using [trailing return type syntax] ?
一个可能的优势:尾随 return 类型是 SFINAE 友好的。
您的 getsum()
函数,尾随 return 类型 (-> 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);
}
但是如果你删除尾随 return 类型
template <typename L, typename R>
auto getsum (L l, R r) // <<--- no more tailing return type!!!
{ return l + r; }
代码不再编译,因为你没有替换失败,而是硬错误。
您的第二个表达式可能 return 与第一个不同。 decltype
的推导规则与 auto
不同。
要获得相同的 return 类型,您必须这样写:
templtate <typename L, typename R>
auto getsum(L l, R r) -> decltype(auto) { return l + r; }
现在来了解两者的优势
第二个片段的优点是不重复表达。如果您有复杂的表达式,重复表达式可能会非常麻烦。
第一个版本的优点是编译器可以对return类型的表达式执行SFINAE。
在 C++20 中,您可以只使用概念来适当地约束函数:
auto getsum(arithmetic auto l, arithmetic auto r) {
return l + r;
}