【问题标题】:When a template is instantiated?何时实例化模板?
【发布时间】:2021-10-20 20:20:12
【问题描述】:

template 在使用之前不会被实例化,例如,如果我有这个类模板:

template <typename T>
struct Pow{
    T operator()(T const& x) const{ return x * x; }
};

void func(Pow<double>); // Pow<double> instantiated here?
void func(Pow<int>){}   // Pow<int> instantiated here?

int main(){
    Pow<int> pi; // instantiated here?
    func(pi); // Pow<int> instantiated here
}
  • 那么模板究竟是什么时候被实例化的呢?

  • Pow&lt;int&gt; 是在声明 func(Pow&lt;int&gt;) 时实例化的吗?

  • 如果我没有在main() 中使用Pow&lt;int&gt;,那么它是否因为在func 中用作其参数的类型而被实例化了?

【问题讨论】:

  • 模板何时被实例化是一个非常复杂、复杂和微妙的问题。这就是我要说的。

标签: c++ template-instantiation


【解决方案1】:

类模板隐式实例化的一般规则如下

[temp.inst]

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

结合这个关于功能的要求:

[dcl.fct.def.general](强调我的)

2 在函数定义中,要么 void declarator ;或声明者;应该是一个格式良好的函数声明,如 [dcl.fct] 中所述。一个函数只能在命名空间或类范围内定义。 函数定义的参数类型或返回类型不应是函数体中不完整或抽象的(可能是 cv 限定的)类类型,除非函数被删除([dcl.fct.def.删除])。

告诉我们检查您的程序所需知道的一切。函数声明不需要类类型是完整的。所以...

Pow&lt;double&gt; 在这里实例化了吗?

没有。这是一个不是定义的函数声明。它不需要参数的完整类类型。 Pow&lt;double&gt; 没有被隐式实例化。

Pow&lt;int&gt; 在此处实例化?

是的。这是一个函数定义,所以需要实例化。

Pow&lt;int&gt; pi; // 在这里实例化?

由于函数已经实例化。

那么模板具体是什么时候实例化的呢?

仅在需要以影响程序语义的方式时使用。

那么Pow&lt;int&gt; 是在声明func(Pow&lt;int&gt;) 时实例化的吗?

func(Pow&lt;int&gt;)定义时。

如果我没有在main() 中使用Pow&lt;int&gt;,那么它是否因为在func 中用作其参数的类型而被实例化?

是的,因为您在函数定义中这样做了。

【讨论】:

  • 好的,非常感谢!
【解决方案2】:

在您的示例中,当编译器看到创建模板类的对象时,它会被实例化:

Pow<int> pi;

C++ 标准说:

17.8.1 隐式实例化 [temp.inst]

1 除非类模板特化已明确 实例化 (17.8.2) 或明确专门化 (17.8.3) 的类 模板特化是隐式实例化的,当 专业化是在需要的上下文中引用的 完全定义对象类型或当类的完整性 类型影响程序的语义...

【讨论】:

  • 非常感谢。
猜你喜欢
  • 2011-06-03
  • 1970-01-01
  • 2012-10-29
  • 2012-03-18
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多