4

使用有什么好处

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;}

在模板实例化期间它不是编译成适当的类型吗?

4

4 回答 4

5

使用[尾随返回类型语法]有什么好处?

一个可能的优势:尾随返回类型是 SFINAE 友好的。

只有在and之间存在加号运算符时,才会启用getsum()具有尾随返回类型 ( )的函数。-> 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);
 }

但是,如果您删除尾随返回类型

template <typename L, typename R> 
auto getsum (L l, R r) // <<--- no more tailing return type!!!
 { return l + r; }

该代码不再编译,因为您没有替换失败而是硬错误。

于 2020-06-29T14:16:48.393 回答
5

一个优势显然是更短的代码。

但也有缺点:除了只能从 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
}
于 2020-06-29T14:14:48.027 回答
1

您的第二个表达式可能与第一个表达式不同。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;
}
于 2020-06-29T14:19:46.050 回答
1

由于 C++14,第二个只是第一个更简单的版本。在 C++14 之前,您可以将函数名称与auto(所以这是关于代码样式)对齐。

于 2020-06-29T14:06:38.737 回答