【问题标题】:what's the process for template function when need to instantiate the same type again later稍后需要再次实例化相同类型时,模板函数的过程是什么
【发布时间】:2019-12-19 01:52:13
【问题描述】:
template<typename T>
int fun(T){
  return 0;
}
int main(){
  fun(0); //#1
  fun(1);  //#2 
}

首先,在#1的调用点,编译器需要为类型“int”(隐式实例化)实例化模板函数,然后将实例化结果用于“fun(0)”,这个过程是没有的问题,但是在调用#2时,编译器是直接使用#2的上述实例化的结果还是进行任何其他过程(例如编译器将为#2实例化但找到上面类型“int”的实例化然后停止实例化并使用上面的结果)?换句话说,当 #2 被调用时,#1 的实例化是否参与重载决议?

更新:
我的另一个问题是,当遇到相同的调用(这里是#2)时,已经实例化(#1的隐式实例化)是否参与重载决议?

【问题讨论】:

  • 查看overload resolution 过程,实例化不起作用,因为它仅依赖于函数声明。一种或另一种方式会产生什么后果?
  • @kmdreko 后果就是编译器是否需要再推演和代换,如果在有stateful meta的代换上下文中,后续结果会大不相同
  • 编译器将在两次调用中插入对方法 fun 的调用,并让链接器稍后解决。在第一次调用时,编译器应该为 int 专门化函数(或者作为最后一步,这里的顺序并不重要,只是编译器的细节)。

标签: c++ templates


【解决方案1】:

在不属于未计算操作数的表达式中调用函数构成对该函数[basic.def.odr]/3 的 odr 使用。 odr 使用需要函数的定义才能存在[basic.def.odr]/4。由于您的示例没有显式专门化或显式实例化函数模板,因此由于在需要定义存在[temp.inst]/4 的上下文中被引用,它将被隐式实例化。据我所知,这几乎是 C++ 标准对此事的全部说明。

因此,您的编译器如何准确处理这取决于编译器的实现。在实践中,我非常怀疑每次源代码中的某些内容需要隐式实例化时,任何理智的实现都会经历完整的模板实例化过程。我不是 clang 也不是 GCC 开发人员,但基于 quick look 到每个源代码中,在我看来,clang 和 GCC 都会简单地记住哪些隐式模板实例化是必需的,实际上在翻译单元结束时执行它们,或者检查实例化是否已经存在并且只执行一次实例化......

【讨论】:

  • 你的回答很有用,但我的第二个问题是已经存在的实例化的定义(通过隐式实例化或显式实例化)是否参与重载决议
猜你喜欢
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
相关资源
最近更新 更多