gpt4 book ai didi

c++ - 为什么标准 C++ 语法不涵盖这种情况?

转载 作者:可可西里 更新时间:2023-11-01 18:36:43 25 4
gpt4 key购买 nike

我主要指的是C++03标准,但快速浏览了一下,它应该也适用于C++11标准。

以下代码在VC++2010中编译执行成功:

template<typename T> 
class CC {
public:
T f(T a) {
return a*a;
}
};
template<>
class ::CC<int> { //<--- ::CC<int> syntax allowed by VC++2010, but is it non-standard ?
public:
int f(int a) {
return a*a;
}
};

int main(int argc, _TCHAR* argv[])
{
::CC<int> c;
}

注意 ::CC<int>引用全局命名空间中定义的模板的语法。这与 NamespaceA::CC<int> 不同:: 的语法运算符前面有东西。使用其他一些工具,我尝试使用严格来自 C++03 的语法来解析它,但它给了我错误,在我看来标准只接受 NamespaceA::CC<int>在类头声明中形成。

仔细一看,问题在于 class-head由标准中的此语法定义:

class-head:
class-key identifier(optional) base-clause(optional)
class-key nested-name-specifier identifier base-clause(optional)
class-key nested-name-specifier(optional) template-id base-clause(optional)

nested-name-specifier形式为 AA::bb:: ...,它不接受我的 ::CC .我的问题是,为什么 C++ 标准不允许使用::CC 形式?这只是我对标准语法的错误解释吗?正确的语法应该是这样的:

class-head:
...
class-key '::'(optional) nested-name-specifier(optional) template-id base-clause(optional)

请注意,上面的形式在其他地方确实被标准使用,例如,在指定 declarator-id 时:

declarator-id:
id-expression
::(optional) nested-name-specifier(optional) class-name

最佳答案

来自 Columbo 的评论,

Of course a nested-name-specifier can be ::, and CC is the identifier, …?

事实并非如此,至少在这个问题的上下文中不是这样。在 C++ 标准的 2014 版之前,裸双分号不符合嵌套名称说明符的条件。该标准的 2003 版表示 nested-name-specifier 采用 BNF 中的两种形式之一:

  • 类或命名空间名称 :: 嵌套名称说明符opt
  • 类或命名空间名称 :: template 嵌套名称说明符

光秃秃的没有空间class ::CC以适应这个规范。 2011 版本为 nested-name-specifier 添加了相当多的 BNF:

  • ::opt 类型名称::
  • ::opt 命名空间名称::
  • decltype-specifier::
  • 嵌套名称说明符 标识符::
  • 嵌套名称说明符 template opt simple-template-id::

这仍然没有给class ::CC留下空间. 2014 版标准最终解决了这个问题,说 nested-name-specifier 是其中之一

  • ::
  • 类型名称 ::
  • 命名空间名称 ::
  • decltype-specifier ::
  • 嵌套名称说明符 标识符 ::
  • 嵌套名称说明符 template opt simple-template-id ::


有很多方法可以查看这个有趣的“功能”。一是这是语言规范中的一个长期存在的错误,于 2002 年首次确定为 issue #355 .编译器供应商的工作之一是识别和修补语言规范中的错误,然后在即将发布的标准中修复这些错误。由此看来,template<> class ::CC<int> {...}应该编译。

另一种观点是,这不是错误。在标准的 2003 和 2011 版本中,嵌套名称说明符 的 BNF 非常清晰,因此 template<> class ::CC<int> {...}不应该编译。这是一个不幸的错误特征还是故意的特征并不重要。题中的代码从这个角度来看应该是编译不出来的。

哪种观点是正确的,值得商榷。最先报告这种差异的问题没有被拒绝,这表明该报告有一些内容。另一方面,标准的两次修订都没有采取任何措施也说明了一些问题。

也就是说,既然标准已经明确,在较新版本的 GCC 中存在一个错误,因为即使指定了 --std=c++14 , 他们不允许 template<> class ::CC<int> {...}编译。

关于c++ - 为什么标准 C++ 语法不涵盖这种情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37132632/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com