我终于开始阅读 c++11,但我无法理解为什么需要尾随返回类型。
我遇到了以下示例,它用于突出问题:
template<class Lhs, class Rhs>
decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;}
该示例是非法的,因为
decltype(lhs+rhs)
不起作用,因为标识符 lhs
和 rhs
仅在解析阶段之后才有效。
我想我的问题是关于
decltype
类型决议的时间安排。如果我没记错的话,关键字 decltype
用于在编译时确定表达式的类型。
我没有看到让
decltype
在所有解析完成后执行类型解析的缺点(这对于上面的示例来说效果很好)。我相信这将是解决问题的更简单的方法......
相反,C++11 标准提供了尾随返回类型:
template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}
我毫不怀疑我错过了一些东西,因为我没有看到尾随返回类型的其他用法。我的推理哪里有缺陷?
尾随返回类型对我来说似乎是一个过于复杂的解决方案,因为在解析完整函数体后进行
decltype
类型解析也可以正常工作?
我没有看到在所有解析完成后让 decltype 执行类型解析的缺点(这对于上面的示例来说效果很好)。
缺点是,如果不从根本上改变 C++ 解析和处理模型的基本基础,这是不可能的。
为了执行您的建议,编译器必须查看
decltype
语法并对语法内容进行一些基本的词法分析。然后,它继续解析更多源文件。在稍后的某个时刻(什么时候?),它决定去,“嘿,我之前看过的那些东西?我现在要为它们做所有的解析工作。”
作为一般规则,C++ 不支持向前查找符号的定义。 C++解析框架的基本假设是,如果符号在使用之前没有声明,则会出现编译错误。 类可以不受前瞻的影响,但仅限于其成员。这部分是因为 id 表达式何时可以引用成员变量(即:如果它没有引用作用域中已声明的本地或全局变量),这一点非常清楚。这里的情况并非如此,我们不确定 id 表达式到底指的是什么。
此外,您的建议会产生歧义。这意味着什么:
int lhs;
template<class Lhs, class Rhs>
decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs);
decltype 语法是指全局
lhs
变量,还是局部
lhs
函数参数?我们现在的做法,两者之间有明确的界限:
int lhs;
float rhs;
template<class Lhs, class Rhs>
decltype(lhs+rhs) adding_func1(const Lhs &lhs, const Rhs &rhs);
template<class Lhs, class Rhs>
auto adding_func2(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs);
adding_func1
指的是全局变量。
adding_func2
指的是函数参数。因此,你可以从根本上破坏地球上所有的 C++ 编译器。或者您可以简单地稍后指定您的返回类型。
或者您可以采用 C++14 方法并且
根本不用费心去说明它typedef decltype(lhs+lhs) foo;
foo lhs;