5

考虑以下示例

template <typename A> struct S 
{
  A a;
  void foo() {}
};  

template <typename T> void bar()
{
  S<void> *p = 0;
}

template <typename T> void baz()
{
  S<void>{}.foo();
}

template <typename T> void qux()
{
  S<void> s{};
}

int main()
{
}

函数模板barbaz并且qux故意不实例化。

baz由于“明显”原因无法在 GCC 和 Clang 中编译的定义-S<void>S. 但是,在这种情况下哪种语言规则有效?

  1. 一方面,S<void>不依赖 的模板参数baz,成员访问要求它是完整的,这就触发了 的实例化S<void>,失败了。需要诊断。

  2. 另一方面,我们有“如果不能为非实例化模板生成有效的特化,则代码格式错误”的总括规则。这使得定义baz不正确。但是,不需要诊断。

更具体地说,我的假设是否正确(如 #1 中所表达),即上述S<void>来自非实例化的引用baz需要实例化S<void>? bar两个编译器都乐于接受 的 定义,它不实例化,这一事实支持了这一假设S<void>

但是,上述编译器对quxClang 抱怨的处理方式不同,而 GCC 则毫无抱怨地接受它。这是其中一个编译器中的错误吗?在这种情况下是否需要诊断?还是我假设#1 在这里工作是错误的?如果#2 是诊断的基础,那么编译器之间的差异是可以接受的。

4

2 回答 2

1

对于bazqux,表达式包括的有效性S<void>只能通过 S 的实例化来完成。然而,编译器没有义务在任何实例化之前执行此验证[temp.res]/8

可以 在任何实例化之前检查模板的有效性。[...] 程序格式错误,无需诊断,如果:

  • 由于不依赖于模板参数的构造,紧随其定义的模板的假设实例化将是格式错误的,
于 2018-12-08T20:11:06.337 回答
1

两者S<void>{}S<void> s{}都在需要实例化 的上下文中使用,由于成员的类型不完整S<void>,这种实例化是格式错误的void

相关的报价是[temp.inst]/1

除非类模板特化已被显式实例化或显式特化,否则当在需要完全定义的对象类型的上下文中引用该特化或当类类型的完整性影响程序的语义时,类模板特化将被隐式实例化. [...]

[temp.arg]/6

如果模板参数的使用在模板特化的实例化中产生了格式错误的构造,则程序是格式错误的。

另一方面,bazquz都是格式不正确的NDR [temp.res]/8

知道哪些名称是类型名称可以检查每个模板的语法。该程序格式错误,不需要诊断,如果:

(8.1) 不能为模板生成有效的特化,[...]

于 2018-12-08T20:12:01.603 回答