"类模板示例<int>;"语句对 C++11 是什么意思?

What does `class template Example<int>;` statement mean with C++11?

本文关键字:语句 C++11 是什么 意思 gt int lt      更新时间:2023-10-16

我被称为"显式模板实例化";在cplusplus.com上,它给出了以下示例:

template <typename T> class Example
{
public:
Example( T test )
{
_data = test;
}
void setTest(T test)
{
_data = T;
}
private:
T _data;
};
class template Example<int>;
class template Example<float>;
class template Example<double>;

除了在我看来像是一个遗漏错误的地方,试图将类型分配给成员变量——_data = T,而不是我认为应该是_data = test——我不明白的是,最后3行到底声明或指示编译器做什么?

我知道模板是什么,已经用它们构建了程序,并且对它们的实例化和专业化有着大致的了解。我可能在理解后两者方面有一些漏洞,但我通常使用例如template class Example<int>;形式而不是代码片段中显示的形式来指示显式模板实例化。

我尝试过使用g++ -std=c++11 -pedantic编译这个片段,它编译得很好,没有任何警告(我首先纠正了上面的_date = T错误(。

这是在我评论了一个相关问题的答案之后发生的,我仍然不确定代码片段中的最后3行是模板专用化还是实例化。

我还试图在ISO发布的C++11草案中找到相关的语法生成规则(在class之后允许template(,但没有找到。

我们可以从下面的godbolt示例中看出,根据clang和MSVC,这是不正确的,并且查看显式实例化部分[temp.extic]的标准草案部分,我看不出gcc接受它的任何理由。

我相信这篇文章"可能"的意思是:

template class Example<int>;
template class Example<float>;
template class Example<double>;

并且这确实是用gcc/clang/MSVC很好地形成的。

看起来在C++11之前,这种语法是允许的,请参阅缺陷报告1707:没有嵌套名称说明符的详细类型说明符中的模板(emphasis mine(:

10.1.7.3中详细说明的类型说明符的语法[dcl.type.elab]部分读取

elaborated-type-specifier:
class-key nested-name-specifieropt templateopt simple-template-id

允许在没有嵌套的名称说明符,例如结构模板S。这是与template关键字的其他用法不一致。可能是最好将生产一分为二,只允许关键字遵循嵌套的名称说明符

因此,-ansi导致警告的注释更有意义。

另一个回答者提交了两份错误报告。

cppreference对显式实例化有很好的假设,这个SO问题是显式实例化——什么时候使用它?解释了为什么这很有用的更多细节。

另请注意,我们可以看到这篇Meta帖子:链接被更改为cppreference.com,该网站已知有不正确的信息,通常社区更喜欢将cppreference作为一个可靠的C++参考。

我在这里看到两个错误:

  1. GCC将这里的template关键字视为template消歧器,从而认为class template Example<int>等价于class Example<int>。这是不正确的,因为C++语法只允许template消歧器在::.->之后(最初编写的C++11允许class template Example<int>,但这已被cwg 1707修复。(
  2. GCC错误地允许class Example<int>;这样的声明。尽管class Example<int>;简单声明的语法匹配,但它未能满足[dcl.dcl]/5中的要求,即简单声明必须声明或重新声明某个东西(class/enumeration/enumerator/typedef/variable/function(

前者被报告为GCC错误87781,后者被报告为GC错误87783。

更新:GCC错误87781现已由r266285修复。