16

From Addison Wesley: C++ Templates

Member function templates cannot be declared virtual. This constraint is imposed because the usual implementation of the virtual function call mechanism uses a fixed-size table with one entry per virtual function. However, the number of instantiations of a member function template is not fixed until the entire program has been translated.

Does the above quote mean that templates have static binding and virtual functions have dynamic binding, that's the reason there cannot be virtual function templates? Please see if a explanation in layman's language is possible.

Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411
  • 1
    Depends on what you mean by binding. You _can_ implement a virtual method by calling a member template. As long as you inline it, any compiler with tail-call optimization will eliminate the overhead – sehe Apr 21 '11 at 10:06
  • 2
    Against SO's terms, just wanted to say this is a **damn good question**. – Qix - MONICA WAS MISTREATED Sep 18 '12 at 08:57

6 Answers6

24

Yes, and no.

The most popular method to resolve virtual function calls is to use a table ("vtable"), where each virtual function maps to an index in the table. This more or less requires that you know the size of the table.

With templates, new functions will be created as needed in different modules. You would then either have to convince the linker to build the table after figuring out the final number of functions, or use some kind of runtime structure to search for available functions at runtime.

On many systems, the linker is part of the OS and knows nothing about C++, so that option is limited. A runtime search would of course affect the performance negatively, perhaps for all virtual functions.

So, in the end, it was decided that it just was not worth the trouble of introducing virtual templates into the language.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Thanks for bothering, You said _"With templates, new functions will be created as needed in different modules."_, I know I am missing some point, isn't that we use templates because we do NOT want to create different functions, we want to use the same function with random parameters? You meant something else, I know, please clarify. – Aquarius_Girl Apr 21 '11 at 13:00
  • doh: now I have read @Tony 's post below and he seems to clarify my above point :) – Aquarius_Girl Apr 21 '11 at 13:01
7

Consider:

struct X
{
    template <typename T>
    T incr(const T& t)
    {
        return t + 1;
    }
};

As incr() is applied to different T types, new functions are generated. Say inside app.c++ you have:

X x;
x.incr(7);        // incr<int>()
x.incr(7.0);      // incr<double>()
x.incr("hello");  // incr<const char*>()

Then as it's compiling app.c++, it sees 3 functions that - if incr were allowed to be virtual - it could make space for the three instantiations above in the virtual dispatch table for X. Then say it loads a shared library at run-time, and the code for that library had 2 instantations of X::incr for uint32_t and std::string::const_iterator. dlopen() would need to grow the existing virtual dispatch table for the already created objects to make space for two new functions. Doesn't sound too horrible, but consider:

  • each bit of code calling virtual functions must know if the address of those functions was bumped along by some offset at run-time (due to dynamic loading of extra instantiations), so there's extra memory and performance cost in every virtual dispatch

  • when there's multiple inheritance, or a derived class is itself derived from, the compiler may want to create a single virtual dispatch table for the total set of virtual functions (one option, there are many for implementing virtual dispatch): in this case, the new virtual functions would either displace other classes' virtual functions or need to be disjoint from the existing ones. Again, more run-time overheads in any scheme to manage this.

So, the very rare occasions when this might be useful aren't worth compromising and complicating the more common case of non-templated virtuals.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
4

Does the above quote mean that templates have static binding and virtual functions have dynamic binding, that's the reason there cannot be virtual function templates?

Basically, yes. More specifically, the static binding causes a problem when the code is being generated to support dynamic binding.

When the compiler compiles the base class, it finds a virtual function and decides to make a virtual function table - this will be used to implement dynamic binding: when a virtual function is called on a derived instance, the compiled code follows a pointer in the instance to the virtual function table for the derived class, then a pointer in that table to the implementation of the virtual function. This table has to include every possible virtual function that could be called. Now, suppose we made a templated virtual function. The function table would need an entry for every instantiation of the template, because any of those functions could conceivably be called at runtime. But the information about what types the template is instantiated with, cannot (in general) be gathered at the time that the virtual function table is generated. (At least, not without playing around with the C++ compilation model.)

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • 1
    thanks, your reply was easier to understand, Question: The vtable is created by the compiler, so when you say that binding is done at the run time, it means, that at run time the linker refers to the table to see which function is where, it is correct? – Aquarius_Girl Apr 22 '11 at 06:34
  • 1
    and in the case of templates, we can't know at the compile time that which instance of a template is going to get called, so we can't place them in the virtual table, is this what you mean? – Aquarius_Girl Apr 22 '11 at 06:43
  • 2
    The linker does nothing at run time. It is part of the compilation process. At compile time, the compiler generates some code. At run time, that code refers to the table. – Karl Knechtel Apr 27 '11 at 17:03
1

virtual functions and templates still work fine together, there is just a small special case which is not implmented.

template<class T>
class A { virtual void f()=0; }; // works fine

class A { template<class T> virtual void f(T t)=0; }; // does not work
tp1
  • 288
  • 1
  • 3
0

Depends on what you mean by binding.

You can implement a virtual method by calling a member template. As long as you inline it, any compiler with tail-call optimization will eliminate the overhead

sehe
  • 374,641
  • 47
  • 450
  • 633
0

Sorta.

You can't really "override" an uninstantiated template because it doesn't even exist in the compiled application. If you instantiate it, then you're not overriding a template, but just another ordinary function. :-)

user541686
  • 205,094
  • 128
  • 528
  • 886