【问题标题】:What does `class template Example<int>;` statement mean with C++11?`class template Example<int>;` 语句在 C++11 中是什么意思?
【发布时间】:2018-10-28 11:14:43
【问题描述】:

我在cplusplus.com 被推荐给"Explicit Template Instantiation",这给出了以下示例:

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&lt;int&gt;; 形式,而不是 sn-p 中显示的形式。

我尝试使用g++ -std=c++11 -pedantic 编译sn-p,它编译得很好并且没有警告(我首先更正了上面的_date = T 错误)。

这是在我评论 an answer to a related question 之后发生的,我仍然不确定 sn-p 中的最后 3 行中的任何一个是模板特化还是实例化。

我也尝试在C++11 draft published by ISO 中找到相关的语法产生规则(在class 之后允许template),但空手而归。

【问题讨论】:

  • 我经常被告知 cplusplus.com 是出了名的糟糕。现在我明白为什么了。写那篇文章的人没有费心检查他们的代码或事实。
  • 您倒退了,cppreference 具有高质量标准。 Cplusplus.com 是可疑的。
  • @HolyBlackCat 从我收集的内容来看,它并没有对class template ... 语法有任何启示。这并不是说我不感谢您在这方面的关注或努力!
  • @amn 正如 StoryTeller 的链接所示,class template ... 似乎根本不是一个有效的语法(尽管 GCC 接受它)。查看您帖子中链接的文章,它们似乎实际上是指template class ...。我链接的段落解释了这种语法。

标签: c++ c++11 templates


【解决方案1】:

我们可以从下面的godbolt example 看到根据clang 和MSVC 的格式不正确,并查看显式实例化 部分[temp.explicit] 的标准草案部分我没有看到任何gcc 接受它的理由。

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

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

确实是is well-formed with gcc/clang/MSVC

看起来在 C++11 之前这种语法是允许的,请参阅 defect report 1707: template in elaborated-type-specifier without nested-name-specifier强调我的):

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

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

允许使用模板关键字而不带 嵌套名称说明符,例如 struct template S。 这是 与模板关键字的其他用途不一致。有可能 最好将生产分成两部分,只允许关键字 在嵌套名称说明符之后,

....

所以with this comment 更有意义的是-ansi 会导致警告。

另一个answerer filed two bug reports

cppreference has a good dicssuion of Explicit instantiation 和这个 SO 问题 Explicit instantiation - when is it used? 详细解释了为什么这很有用。

另外请注意,我们可以看到这个 Meta post: Links being changed to cppreference.com 已知该站点包含不正确的信息,并且通常社区更喜欢 cppreference 作为可靠的 C++ 参考。

【讨论】:

  • 关于“这篇文章的意思”——我也认为 cplusplus.com 中的示例似乎不是 C++ 示例中质量最好的,_date = T 错误.它显示的实例化模板的特定方式可能在标准标准化模板实例化之前是“标准的”,并且从中得到了怪癖。就目前而言,除了可能得出的结论之外,很难说 GCC 会验证它,因为它允许这种语法设计或错误(一个错误)。
  • @amn 这可能是一个古老的残留咒语......但在这种情况下使用-pedantic(我使用)应该会产生诊断。我将深入研究它,但如果这还不是错误报告,则应该报告它。
  • 我刚刚使用了 -ansinow GCC 确实 抱怨 class template ... 行,如果有的话,会出现警告或错误-pedantic-pedantic-errors 分别存在。我觉得这很奇怪,因为正如我从 this answer 了解到的那样,C++ 从来没有被 ANSI 标准化,那么为什么这两个开关会一起为 GCC C++ 编译器工作......
  • @amn 哦,有趣的是,即使考虑到他们通过诊断提供的额外信息,我仍然认为它是不成熟的。
  • @amn IIUC 正确,ISO 文件也是 ANSI 文件,所以调用 ANSI 标准在技术上是准确的。
【解决方案2】:

我在这里看到两个错误:

  1. GCC 将这里的template 关键字视为template disambiguator,因此认为class template Example&lt;int&gt; 等价于class Example&lt;int&gt;。这是不正确的,因为 C++ 语法只允许 template 消歧器位于 ::.-&gt; 之后。 (最初编写的 C++11 允许 class template Example&lt;int&gt;,但这已由 cwg 1707 修复。)
  2. GCC 错误地允许像class Example&lt;int&gt;; 这样的声明。虽然class Example&lt;int&gt;; 匹配simple-declaration 的语法,但它不符合[dcl.dcl]/5 中的要求,即简单声明必须声明或重新声明某些东西(类/枚举/枚举器/typedef/变量/函数)。李>

前者被举报为GCC bug 87781,后者被举报为GCC bug 87783

更新:GCC bug 87781 现在由r266285 修复。

【讨论】:

  • 我通常会链接到引发错误报告的 SO question,这允许发现或处理错误报告的人直接在此处发表评论。这可能很有用,因为提交错误报告的人可能不再处于活动状态等......所以即使错误报告得到更新,答案也可能不会。
猜你喜欢
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2012-01-05
相关资源
最近更新 更多