Work around for limitation of template virtual member functions?

Hi

I have a Message class which other classes inherit from. The inherited classes will need to have a serialisation member function. I would like to make these member functions virtual (so that I take advantage of dynamic dispatch).

So as an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  class Message
  {
     private:
       int x;

     public:

     virtual void serialise(char* str)
     {
          // do serialisation
     }

  };

  class MessageWStr : public Message
  {

     private:
       
        string str;

     public:

     virtual void serialise(char* str) override
     {
          // do serialisation
     }

  };


The problem arises with the serialisation library which I'm using which requires the class (being serialised) to have a template member function of the form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// in Message
template <typename T>
void serialize(T& t)
{
   t.saveInt(x); // serialisation library function - serialises member variable x
}

// in MessageWStr
template <typename T>
void serialize(T& t)
{
   t.saveStr(str); // serialisation library function - serialises member variable str
}



However, I cannot make these functions virtual as apparently c++ does not permit virtual template member functions.

I wondered if anyone might know of a solution to this problem?

Thanks
Last edited on
You could use some special-case code for each class, or exploit that T is constrained and put it inside some polymorphic wrapper.

To restate, the problem is to call A::f polymorphically.
1
2
3
struct A    { template <typename T> void f() {}; };
struct B: A { template <typename T> void f() {}; };
struct C: A { template <typename T> void f() {}; };


The first way is just to have some special cases:
1
2
3
4
5
6
template <typename T>
    void f(A* pa)
    {
      if (B* pb = dynamic_cast<B*>(pa)) pb->f<T>(); else
      if (C* pc = dynamic_cast<C*>(pa)) pc->f<T>(); else pa->f();
    }

And then to arrange to call this instead of f, which can essentially be done by implementing a less-general version of the visitor pattern and making this function into the visitor.

A second way is to exploit the commonality between every T that is passed to serialize. An example of that commonality could be that every T has a member function whose signature is void saveInt(int).

Maybe look up "visitor pattern" and "c++ type erasure".
Last edited on
Topic archived. No new replies allowed.