-1

In c++, it is not possible to create virtual template functions. Reason as I understand is that, we cannot create a base class with the virtual table with infinite number of matching functions. What I want to clarify is, whether this is a limitation of current c++ compilers? Or is it purposely enforced rule to avoid some other resulting problems?

When I tried to use virtual template functions in my code, compiler throws an error. "error: templates may not be ‘virtual’"

p.s. sample code

class A {
public:
    template <typename T>
    virtual void doStuff(T value) const {
        cout << "A:doStuff " << value << endl;
    }

    virtual ~A() {}
};

class B : public A {
public:
    template <typename T>
    void doStuff(T value) const override {
        cout << "B:doStuff " << value << endl;
    }
};

int main() {
    A* a1 = new B();
    a1->doStuff(1);  

    A* a2 = new B();
    a2->doStuff(1.1); 

    delete a1;
    delete a2;

    return 0;
}
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
De Abrew
  • 21
  • 3
  • One interesting question would be, whether there is a solution, when you know that all template instances of this function are overridden together or not at all, so that theoretically you would need only one entry in the virtual table. Or more strict, if all descendants each definitely override the template. – Sebastian Aug 05 '23 at 10:16
  • An infinite size vtable surely would be a problem. :-) Some other languages will instead do a runtime search for a matching function. C++ apparently didn't want that. – BoP Aug 05 '23 at 10:24
  • The problem should become obvious, if you consider the fact that the function could be used in different translation units or even from within and from outside of a libraries: None of the translation units "knows" about the vtable the other needs so you'd need to restart compilation during the linking phase or even later; I don't know any C++ compiler that does not allow you to separate compilation and linking into seperate calls to the compiler/linker program(s). – fabian Aug 05 '23 at 10:56
  • I don't understand the question. You understand why it's not possible, so why do you say "current" compilers? – HolyBlackCat Aug 05 '23 at 11:06
  • Because virtual functions and template functions model two different (mutually exclusive ) concepts : Dynamic polymorphism (virtual functions, runtime) and Static polymorphism (meta template programming, compile time). E.g. [more about static vs dynamic polymorphism](https://www.modernescpp.com/index.php/more-about-dynamic-and-static-polymorhism/#:~:text=Dynamic%20polymorphism%20happens%20at%20run,performance%20costs%20at%20run%20time.) – Pepijn Kramer Aug 05 '23 at 11:46
  • 1
    To accommodate having a virtual template member function, that would preclude having the traditional style translation units. Now with **modules** and **whole program optimization**, it may be feasible to have virtual template member functions. As with all changes to the C++ standard, that would have to be presented as a **proposal**. – Eljay Aug 05 '23 at 12:09
  • 1
    You're right to be skeptical of 'infinite virtual table" as an argument. That's are an implementation technique, not a design goal. But the more fundamental problem is that C++ is designed around separate compilation and dumb linkers: when `a.cpp` is compiled the compiler doesn't know anything about `b.cpp`. If `a.cpp` defines a virtual template function and `b.cpp` provides an overriding specialization, how can the code in `a.cpp` call that function? Either separate compilation has to go away, or the system has to implement some runtime lookup. Neither is acceptable. – Pete Becker Aug 05 '23 at 12:19
  • @PeteBecker, just to clarify, lets say we define everthing in one single file to eliminate the problem of multiple translation units. Is this limitation there, beacause we cannot add new functions to vTable (of the base class, or both base and drived classes) one by one when new instantiations are seen by the compiler. Consider below instantations. a1->doStuff(1); a2->doStuff(1.1); Is this the behaviour you express by the term 'run time lookup'? Or the actual program run time. – De Abrew Aug 05 '23 at 14:58
  • 1
    If we have all in one TU, then we (and compilers) might de-template the code... – Jarod42 Aug 05 '23 at 16:52
  • @DeAbrew -- as I said, if you eliminate separate compilation (one way is to require that everything go in a single source file, which will result in prohibitively long compilation times for non-trivial programs) you can do pretty much what you want here. – Pete Becker Aug 05 '23 at 17:09
  • If you would eliminate dynamic libraries, multiple translation units could be compiled like a single translation unit. – Sebastian Aug 05 '23 at 17:46

0 Answers0