尾随返回类型中 decltype 的原因

inq*_*uam 5 c++ decltype c++11 trailing-return-type

我正在阅读一篇有关“新”C++ 功能的文本,并遇到了decltype及其用法。我理解尾随返回类型中decltype背后的推理,例如

template <typename lhsT, typename rhsT>
auto add(lhsT& lhs, rhsT& rhs) -> decltype(lhs + rhs) {
    return lhs +rhs;
}
Run Code Online (Sandbox Code Playgroud)

如果没有它,编译器将无法导出模板函数的返回类型。但为什么语法是这样的呢?

为什么不使用类似的东西

template <typename lhsT, typename rhsT>
decltype(lhs + rhs) add(lhsT& lhs, rhsT& rhs) {
    return lhs +rhs;
}
Run Code Online (Sandbox Code Playgroud)

感觉更“自然”,因为返回类型是在通常的位置声明的,尽管是两个参数的结果。这是否与其他内容发生冲突,或者如果语法是这种不值得的方式,它是否会给编译器带来额外的工作?

Snp*_*nps 5

笔记

\n\n
\n

如果没有它,编译器将无法导出模板函数的返回类型。

\n
\n\n

后来在 C++14 中修复了这个问题,编译器不需要尾随返回类型,因为它可以从返回的表达式推断返回类型。以下内容在 C++14 中运行良好。

\n\n
template <typename lhsT, typename rhsT>\nauto add(const lhsT& lhs, const rhsT& rhs) {\n    return lhs + rhs;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n
\n

但为什么语法是这样的呢?

\n
\n\n

当从参数推导返回类型时,使用尾随返回类型非常有用,参数总是在返回类型之后声明(不能引用尚未声明的内容)。

\n\n

此外,从函数和数学符号使用这种声明的意义上来说,尾随返回类型确实看起来更自然。我认为 C 风格声明之外的大多数表示法类型通常都使用尾随返回类型。例如

\n\n
\n

f : X \xe2\x86\x92 Y

\n
\n\n

在上面的数学符号中,f是函数名、X参数和Y返回值。

\n\n

仅仅因为粉红色的羊群拒绝灰色的羊并不意味着它不自然。

\n\n

在您的第二个示例中,编译器不可能根据上述原因推断返回类型,参数尚未声明。但是,如果使用模板参数 和 ,则可以进行推断std::declval例如

\n\n
template <typename T, typename U>\ndecltype(std::declval<T>() + std::declval<U>()) add(const T& lhs, const U& rhs) {\n    return lhs + rhs;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

std::declval充当类型的惰性实例化并且从不计算,例如,调用构造函数等。它主要在推断类型时使用。

\n