箭头语法在函数声明中的优点

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 )),只有在 lr 之间存在加号运算符时才会启用。

如果你用几个不支持总和的参数调用它(例如,几个 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;
}