Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template specialization of pure virtual function

How can I specialize a templatized function which is defined as a pure function in the base class?

struct A {
    virtual void func(int a) = 0;
    //virtual void func(int a) {} // replace above line with this and it works
};

struct B : public A {
    template<typename T> void func(T t) {
        cout <<"hello"<<endl;
    }
};
template<> void B::func<int>(int a) { cout <<"hello 2"<<endl; }


int main() {
    B b;
    b.func(2);
}

Error:

error: variable type 'B' is an abstract class B b; ^ note: unimplemented pure virtual method 'func' in 'B' virtual void func(int a) = 0;

like image 452
Nujufas Avatar asked Sep 02 '25 15:09

Nujufas


1 Answers

Virtual function could be overridden by only non-template functions. In this case,

Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).

And note that function templates can't be virtual functions;

Functions templates cannot be declared virtual.

From the standard, [temp.mem]/4

A specialization of a member function template does not override a virtual function from a base class. [ Example:

class B {
  virtual void f(int);
};

class D : public B {
  template <class T> void f(T); // does not override B​::​f(int)
  void f(int i) { f<>(i); }     // overriding function that calls the template instantiation
};

— end example ]

About your question,

why it works if the function is made 'not pure'?

The compliation error disppears but it still doesn't work as you expected; the function template in the derived class doesn't override the virtual function of the base class. You can check it with dynamic dispatch:

If a derived class is handled using pointer or reference to the base class, a call to an overridden virtual function would invoke the behavior defined in the derived class.

Note that you should use pointer or reference to make dynamic dispatch works, e.g.

B b;
A* pa = &b;
pa->func(2);

LIVE

You can also apply override specifier to help you confirm overridding.

like image 159
songyuanyao Avatar answered Sep 08 '25 05:09

songyuanyao