首页 文章

从非实例化的上下文中引用特定的模板特化:实例化与否?

提问于
浏览
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()
{
}

功能模板 barbazqux 故意不进行实例化 .

baz 的定义无法在GCC和Clang中编译"obvious"原因 - S<void>S 的无效专门化 . 但是,在这种情况下,哪种语言规则正在起作用?

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

  • 另一方面,我们有"if no valid specialization can be generated for a non-instantiated template, the code is ill-formed"的一揽子规则 . 这使得 baz 的定义不合理 . 但是,不需要诊断 .

更具体地说,我是否正确地假设(如#1所示)上述对非实例化 bazS<void> 的引用需要实例化 S<void> ?两个编译器都乐于接受 bar 的定义这一事实支持了这一假设,该定义并未实例化 S<void> .

然而,上述编制者对他们的处理方式有所不同--Clang抱怨,而GCC接受它没有任何投诉 . 这是其中一个编译器的错误吗?在这种情况下是否需要诊断?或者我错误地假设#1在这里工作?如果#2是诊断的基础,那么编译器之间的差异是可以接受的 .

2 回答

  • 1

    S<void>{}S<void> s{} 都在需要实例化 S<void> 的上下文中使用,这样的实例化由于成员类型 void 不完整而格式不正确 .

    相关报价为 [temp.inst]/1

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

    [temp.arg]/6

    如果在模板专业化的实例化中使用template-argument会导致格式错误的构造,则该程序是不正确的 .

    另一方面, bazquz 都是格式错误的NDR [temp.res]/8

    了解哪些名称是类型名称允许检查每个模板的语法 . 如果出现以下情况,该程序格式错误,无需诊断:(8.1)无法为模板生成有效的专业化,[...]

  • 1

    对于 bazqux ,包含 S<void> 的表达式的有效性只能通过S的实例化来完成 . 但是,编译器不会在任何实例化之前执行此验证[temp.res]/8

    可以在任何实例化之前检查模板的有效性 . [...]该程序格式错误,无需诊断,如果:由于不依赖于模板参数的构造,在其定义后立即对模板进行假设实例化将是不正确的,

相关问题