5

I was wondering that when I create an instance of a class template with specifying the template type parameter.
1) why the non-called function do not get instatiated ? .
2) dont they get compiled until I try to use it ?
3) what is the logic behind this behavior ?

Example

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();

 }
4

4 回答 4

6

Templates aren't code - they're a pattern used to make the actual code. The template isn't complete until you supply the parameters so the code can't be made ahead of time. If you don't call a function with a particular set of template parameters, the code never gets generated.

于 2012-06-28T20:35:14.430 回答
3

If they instantiated the entire class, then you might get invalid code.

You don't always want that.

Why? Because in C++, it's difficult (and in some cases, outright impossible, as far as I know) to say, "only compile this code if X, Y, and Z are true".

For example, how would you say, "only my copy constructor if the embedded object can be copied"? As far as I know, you can't.

So they just made them not compile unless you actually call them.

于 2012-06-28T20:32:38.347 回答
3

To embellish a little more: this is typically called duck typing, and the bottom line is that it allows you to write "class patterns" of which some member functions may apply when instantiated with one template type, other members may apply when instantiated with a second template type, and by only requiring the ones you actually call to compile, you get to write a lot less code for operations that wind up being common ones.

By not requiring all member functions to be compiled you get all the niceties of static type checking on the functions that actually are compiled.

For example, imagine you had:

  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
  };

Then you have

  // 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;        
于 2012-06-28T21:01:00.903 回答
2

No code is generated for cat<int>::show() because you never call it. If you did call it you would get a compilation error. Template functions which are never called do not exist.

Templates are little more than test substitution mechanisms. This makes them very powerful. You, as the programmer, may want to create a cat<int> knowing that you will never call show() or call anything else that would be invalid. The compiler lets you know if you did, so it works out nicely.

So if your question is "why does it work this way", I would ask you "why not"? It's a design choice. This choice allows me to use a template type safely and still benefit from other parts of the code. What's the harm? You also generate less code, which is a good thing, right?

于 2012-06-28T20:32:08.610 回答