【问题标题】:Certain errors in uninstantiated template not reported by g++g++ 未报告未实例化模板中的某些错误
【发布时间】:2014-07-24 12:22:29
【问题描述】:

考虑这个例子:

class A
{
  void foo();
  public:
  void bar();
};

template <class> class B
{
  B()
  {
    A a;
    a.foo();    // 1
    A::bar();   // 2
    a.bar(1);   // 3
  }
};

注意B 永远不会被实例化。

clang++ 将所有三个标记的行报告为错误。 g++ (4.8.3) 接受行 12 并且只报告行 3

如果 B 被实例化,g++ 很高兴将所有三行报告为错误。

这是g++ 错误吗?有人会这么认为。 A 不是从属名称,应在模板定义时正常检查其成员。有没有我看不到的细微差别?

【问题讨论】:

  • 1 可以通过 friend 声明对专业化有效,通过派生 A 可以使 2 对于专业化有效,而 3 永远不能对专业化有效。
  • @SanderDeDycker A 不是模板,它的所有朋友(没有)都是已知的。 B 当然可以有一个派生自A 的专业化,但是这个B::B 不会是该专业化的成员。
  • 我的想法与hvd's answer 相同。 IE。检查 1 和 2 是否无效比检查 3 是否无效更难,并且由于不需要错误,因此可以接受最小的努力。

标签: c++ templates g++


【解决方案1】:

那些预实例化消息不是由标准强制执行的,而是由编译器决定的

n3337 § 14.6 - 8

不应为模板定义发出诊断 可以生成有效的专业化。如果没有有效的专业化可以 为模板定义生成,并且该模板不是 实例化,模板定义格式错误,无诊断 需要。

强调我的

【讨论】:

  • 我从没想过引用的段落指的是这样的错误。但是在重新阅读标准中的相关页面后,我发现您是对的。甚至像 int* i = 23.45; 这样的东西也可能无法诊断。
【解决方案2】:

通常无法在模板定义时判断 a.foo();A::bar(); 是否是错误,即使对于 A::fooA::bar 的那些特定定义也是如此。

一般来说,a.foo(); 可能是有效的,如果 A 有一些 B&lt;T&gt; 作为朋友而不是其他的特化,这将使有效性取决于模板参数。

一般来说,如果B&lt;T&gt; 直接或间接地将A 作为基类,并且模板类通常在模板定义时还不知道它们的基类,那么A::bar(); 可能是有效的。

尽管可以检测到这两种情况都不可能在这里A 没有朋友,B&lt;T&gt; 没有基础),但它需要付出巨大的努力却收效甚微。因此,总是在实例化时简单地执行此类检查是有意义的,这就是 GCC 所采用的方法。

C++ 中实际上没有规则要求在模板定义时进行诊断(正如 Marco A. 的回答正确指出的那样)。只有当模板被实例化时,模板定义中的任何错误都会导致程序格式错误,需要诊断,根据 2.2p1 要点 8:

如果任何实例化失败,则程序是非良构的。

在你的程序中,没有实例化,所以没有实例化失败。

【讨论】:

  • 没关系,我应该阅读更完整的;我停在这两个“可能有效”之后,因为它不能在这里。
  • @MatthieuM。啊,谢谢你的澄清。希望这个编辑可以防止其他人像你一样阅读它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2021-09-02
  • 1970-01-01
  • 2013-07-21
  • 2014-04-20
相关资源
最近更新 更多