1

例如,前向声明和来自维基百科的替代函数语法部分

Ret 类型是添加 Lhs 和 Rhs 类型将产生的任何内容。即使使用 [...] decltype,这也是不可能的:

template<class Lhs, class Rhs>
decltype(lhs+rhs)  //Not legal C++11
      adding_func(const Lhs &lhs, const Rhs &rhs) {
  return lhs + rhs;
}

这不是合法的 C++,因为 lhs 和 rhs 尚未定义;在解析器解析函数原型的其余部分之前,它们将不是有效的标识符。

当系统处于主要内存压力下时,这是可以理解的(它允许传递作为流操作完成)。但是,在这个时代(我的智能手机有足够的 RAM 来保存完整的源代码、完整的解析树,然后是一些用于任何合理文件的内存)为什么令牌的顺序很重要?语法中是否存在一些奇怪的极端情况,例如,decltype除非您知道其中的标识符是类型还是变量,否则无法找到非终结生产的结尾?另外一点,为什么全局/命名空间范围声明的顺序很重要?


编辑,原来这是合法的:

class foo {};
foo Foober(int foo) { return ::foo(); }

如果我在野外遇到这种情况,它最终会出现在 The Daily WTF 上,但它仍然是合法的。

4

4 回答 4

4

声明“这不是合法的 C++”并不十分准确。在函数声明出现的范围内定义lhs并定义了合法的 C++ 。rhs参数lhsrhs不在外部范围内,但名称肯定有可能在其他声明的范围内;改变函数返回类型的范围可能会默默地改变以前有效程序的含义。

在 C++ 中,作用域并不总是按词法顺序排列。例如,在成员函数体内,所有成员都是可见的,即使是尚未声明的成员。(前导返回类型也不是成员函数体的一部分,但尾随返回是。)

语法中是否存在一些奇怪的极端情况,例如,除非您知道其中的标识符是类型还是变量,否则无法找到 decltype 非终端生产的结尾?

我不这么认为;的论点周围的括号decltype应该是明确的。但是,如果您不知道标识符是否是模板,那可能会以非常微妙的方式影响<>标记>>的含义。并且不知道标识符是类型还是函数也会在解析表达式时产生困难(即使在 C 中也是如此)。因此,在某些极端情况下,名称的“种类”很重要。

于 2013-01-17T21:51:57.287 回答
4

这不是容量问题,而是向后兼容性问题。

该语言的新版本必须保留几乎所有旧功能以保持向后兼容性。在原始 C++ 中,成员函数返回类型不在类或函数的范围内查找。它是在函数声明的封闭范围内查找的。更改此规则对于向后兼容性可能是灾难性的。

解决它的唯一方法是专门针对decltype参数进行例外处理。但这将非常不一致并且容易出错。

于 2013-01-17T22:27:34.000 回答
1

他们必须在某处划定“内部”和“外部”范围之间的界限。正如您所提到的,当可以解析其中的标识符时,更容易找到生产的结尾。它更容易在编译器中实现,并且更容易在语言标准中一致地指定。这可能是第一个编译器这样做的原因,以及为什么语言总是需要typenameandtemplate关键字来解决模板扩展中未定义(嵌套)标识符引起的语法歧义。

并且标识符在出现在声明中之前永远不能使用,这是帮助人类或机器阅读器找到相关声明的绝妙规则。(除了类成员之间,应用了特殊的两次解析以提高便利性。)

一旦以一种方式完成,就做出了承诺,并且语言不能改变。除了添加一个特性之外,这就是 C++11 解决问题的方式。

template<class Lhs, class Rhs>
  auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs)
    {return lhs + rhs;}

顺便说一句,他们没有提到另一种解决方法:

template<class Lhs, class Rhs>
  decltype( declval< Lhs >() + declval< Rhs >() )
    adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;}
于 2013-01-17T22:29:29.620 回答
1

您的前提是前向声明纯粹是为了节省内存以允许流解析(而不是将整个源文件保存在内存中)并不是真正正确的。

我们使用的许多解析算法都是基于前向传递,如果你必须回溯,它会在解析时间(或空间)上产生指数爆炸以消除歧义。

例如 - 在声明之前暂时接受一个标识符而不知道它是什么 - 意味着您必须暂时继续进行解析,以考虑它是什么的所有可能性。(包括但不限于错字)

于 2013-01-18T11:55:49.187 回答