为什么不实例化未调用的模板类成员?

Why uncalled template class members aren't instantiated?

本文关键字:成员 实例化 调用 为什么不      更新时间:2023-10-16

当我创建指定模板类型参数的类模板实例时,我想知道这一点。
1)为什么非调用函数没有被激活?
2)在我尝试使用它之前,它们不会被编译吗?
3)这种行为背后的逻辑是什么?

template <class T>
class cat{
public:
T a;
void show(){
   cout << a[0];
}
void hello(){
   cout << "hello() get called n";
}
}; 
int main(){
cat<int> ob1; // I know that show() did not get instatiated, otherwise I will get an    error since a is an int
ob1.hello();
 }

模板不是代码 - 它们是用于制作实际代码的模式。在提供参数之前,模板不完整,因此无法提前创建代码。如果不使用一组特定的模板参数调用函数,则永远不会生成代码。

如果他们实例化了整个类,那么你可能会得到无效的代码。

你并不总是想要这样。

为什么?因为在C++中,很难(在某些情况下,据我所知,完全不可能)说,"只有在 X、Y 和 Z 为真时才编译此代码"。

例如,你会怎么说,"如果嵌入对象可以复制,只有我的复制构造函数"?据我所知,你不能。

所以他们只是让它们不编译,除非你真的调用它们。

再修饰

一点:这通常称为鸭子类型,底线是它允许您编写"类模式",当使用一种模板类型实例化时,某些成员函数可能会应用,其他成员在使用第二个模板类型实例化时可能会应用,并且只需要您实际调用的模板进行编译, 您可以为最终成为常见操作的代码编写更少的代码。

通过不要求编译所有成员函数,您可以获得对实际编译的函数进行静态类型检查的所有细节。

例如,假设您有:

  template <typename E> 
  class myContainer {
      // Imagine that constructors, setup functions, etc. were here
      void sort();   // this function might make sense only if E has an operator< defined
      E max();   // compute the max element, again only makes sense with a operator<
      E getElement(int i);  // return the ith element
      E transmogrify();  // perhaps this operation only makes sense on vectors
  };

然后你有

  // sort() and getElement() makes total sense on this, but not transmogrify()
  myContainer<int> mci;         
  // sort and max might not be needed, but getElement() and transmogrify() might
  myContainer<vector<double>> mcvd;        

不会为cat<int>::show()生成任何代码,因为您从不调用它。如果您确实调用了它,则会出现编译错误。 从不调用的模板函数不存在。

模板只不过是测试替换机制。 这使它们非常强大。 作为程序员,您可能希望创建一个cat<int>,因为您知道您永远不会调用show()或调用任何其他无效的内容。 编译器会让您知道您是否这样做了,因此效果很好。

因此,如果您的问题是"为什么它以这种方式工作",我会问您"为什么不"? 这是一个设计选择。 此选项允许我安全地使用模板类型,并且仍然可以从代码的其他部分中受益。 有什么危害? 你生成的代码也更少,这是一件好事,对吧?