4

给出以下示例代码

struct S;

template<typename>
class C
{
public:
   void f(bool b)
   {
      if (b)
        g();
   }

   void g()
   {
     S{};
   }
};

int main()
{
   C<int>{}.f(false);
}

GCC 正确报告以下内容:

example.cpp: In instantiation of 'void C< <template-parameter-1-1> >::g() [with <template-parameter-1-1> = int]':
10 : required from 'void C< <template-parameter-1-1> >::f(bool) [with <template-parameter-1-1> = int]'
21 : required from here
15 : error: invalid use of incomplete type 'struct S'

我现在的问题是:这种有保证的行为是否在标准或任何其他文件中有一些规定?

更准确地说我的问题:

C是一个模板类,它的成员只有在被引用f()g()才会被实例化。f()中引用main()。如果我不引用g()(它在内部尝试使用不完整的类型),则代码将编译。但是g()在 if-branch inside 中被引用f()。这个分支确定性地永远不会被执行。因此编译器可能会忽略/删除这个死代码分支,从而避免实例化g()(以及尝试使用不完整类型的错误)。但是,这并没有发生(至少在我尝试过的编译器上)。

我知道允许这样做只会通过调整编译器的优化设置将非法代码变成合法代码,但我的问题仍然是这个代码示例是否由于某些规则(例如优化顺序与模板传递)而保证失败可以在某处阅读。

感谢您的任何见解。

4

2 回答 2

3

内联和死代码删除优化可以防止模板实例化吗?

不。

死代码删除是一种优化,可以执行以根据优化器的规则删除未“使用”的代码。只要实现希望保持完全合规,这种优化可能不会违反“as-if”规则。

无论如何,这个程序是错误的。C<int>在…中找到的调用完全需要实例化 of main,这是不可能的。如果此实例化成功,那么它的未使用部分可能已被优化掉,但这是“稍后”的一步。您只能删除最初物理上能够“存在”的程序的未使用部分。

询问是否需要实现来防止编译这种格式错误的程序可能会很有趣如果它以后可能会删除有问题的代码。我们可以通过引用标准中定义“格式错误” 的任何段落来轻松回答这个问题。但这既是一个不同的问题,而且在我看来,顺便说一句。

如果您有兴趣,我们不能在一般情况下对这个问题做出肯定的回答,因为某些形式不正确的情况可以用“无需诊断”这一短语来限定。但是,如果不存在该短语,需要进行诊断。(不要让我这么说。)

于 2016-08-04T22:50:30.497 回答
2

优化是允许编译器应用于有效程序的东西。由于 S 未定义,因此无法实例化,因此您的程序无效。优化器进来使程序有效为时已晚。

于 2016-08-04T22:45:35.867 回答