Why no virtual member templates?

T

Tom Craig

A few times recently I've wanted to use a virtual member template,
like this:

struct A {
template<class T> virtual void f();
};

Unfortunately, the C++ standard forbids this. I'm a bit confused about
this: Why should virtual member templates be forbidden?

The only (well, "only") reason I've come across is that, when
compiling the class, the compiler doesn't know how many entries to put
in the vtbl. Couldn't this be worked around by adding an extra level
of indirection? In particular, the entry for f in A's vtbl would index
into a map from types to function addresses. When the linker combines
the objects, it *does* know how many entries are required (and what
they are), so it can resolve the calls - either by keeping the extra
level of indirection in at run-time or by expanding the class's vtbl
to the correct size.

Or have I got the wrong end of the stick? I'm interested in knowing
because (a) I've recently been developing an increasing interest in
the way compilers and linkers work, and (b) virtual member templates
would be *sooo* very useful.
 
A

Andrey Tarasevich

Tom said:
A few times recently I've wanted to use a virtual member template,
like this:

struct A {
template<class T> virtual void f();
};

Unfortunately, the C++ standard forbids this. I'm a bit confused about
this: Why should virtual member templates be forbidden?

A template needs to be specialized in order to get instantiated. I.e.
all template parameters have to be assigned concrete argument values at
compile time. In case of function templates, these template arguments
are either deduced from function argument types or explicitly specified
by the user at the point of the call. In order to do something like that
for virtual functions the compiler has to be able to perform the global
analysis of the entire program and then generate all versions of virtual
functions that might potentially be called at run time. The compiler has
no means to determine which of these (possibly numerous) versions are
really needed and which are not. The language specification usually
avoids any requirements that would force compilers to perform global
analysis of the code, which is one reason why template virtual functions
are not allowed.
 
J

James Kanze

A few times recently I've wanted to use a virtual member
template, like this:
struct A {
template<class T> virtual void f();
};
Unfortunately, the C++ standard forbids this. I'm a bit
confused about this: Why should virtual member templates be
forbidden?
The only (well, "only") reason I've come across is that, when
compiling the class, the compiler doesn't know how many
entries to put in the vtbl. Couldn't this be worked around by
adding an extra level of indirection? In particular, the entry
for f in A's vtbl would index into a map from types to
function addresses. When the linker combines the objects, it
*does* know how many entries are required (and what they are),
so it can resolve the calls - either by keeping the extra
level of indirection in at run-time or by expanding the
class's vtbl to the correct size.

It would also have to instantiate the templates for the
functions in the derived classes, ensuring that they are placed
in the correct slots in the indirect vtable. This becomes
particularly interesting when dynamic linking is used, but even
without dynamic linking, it requires a lot more than is
available with current linkers.
Or have I got the wrong end of the stick? I'm interested in
knowing because (a) I've recently been developing an
increasing interest in the way compilers and linkers work, and
(b) virtual member templates would be *sooo* very useful.

Lots of things we don't really know how to implement effectively
would be *sooo* very useful.
 
J

James Kanze

A::f isn't a function, it's a function template.

Yes, but each specialization is a function. And the code you
write to implement it does look a lot like that you'd write in a
function.
Do you mean that you would like to generate a separate virtual
function for each instantiation of f?

That's what it would mean, wouldn't it. Each specialization of
f is a separate virtual function.
How would you ever override f?

The same way you override any virtual function, no. A function
template with the same signature in the derived class.
(I suppose you could declare struct B: A { template<class T>
virtual void f(); };, with the proviso that instantiations of
B::f override matching instantiations of A::F, but that seems
like a maintenance nightmare waiting to happen.)

In the simpler cases (no explicit specialization), I don't see
where it would cause the user any more problems that a normal
virtual function. (On the other hand, just specifying what
happens if there are explicit specializations for some of the
cases sounds like a major problem to me.)

The real reason we don't have it, however, is that no one could
figure out how to reasonably implement it. If you use dynamic
linking, for example, it would mean that the dynamic linker
would have to be able to instantiate templates; if you used a
sub-table of the vtable, as the original poster suggested, the
dynamic linker would have to be able to find all of the existing
vtables for the class, and increase the size of this subtable.
Even without dynamic linking, the linker would still have to
work out which instantiations were needed: you'd need an
instantiation of Derived::f< int >, for example, if anyone calls
For what, exactly? Templates are compile-time entities,
whereas virtual functions exist specifically to support
run-time indirection.

Still, it's a rare program that doesn't use both, at various
times. And once or twice I've found that they would have been
convenient, if they'd have been available.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top