T
tirath
Hi all,
I have a templated class that derives from a non-templated abstract class.
How do I then cast a base class pointer to a <templated> derived class
pointer in a generalised fashion?
Here's what I'm generally trying to achieve:
I'm building (trying to anyway) a serialization library. Here's my design:
SPair<SP1, SP2> derives from Pair<P1,P2> and Ser:
Ser <___________SPair <SP1, SP2>
Pair<P1,P2> <____|
Each time a Serializable Object (SObject) is created, the ctor registers the
'this' pointer onto a serialisation list held statically in the abstract
base class (Ser); the list holds Ser* - i.e. base class pointers. Each
SObject's dtor is reponsible for removing the 'this' pointer from the list
when the object falls out of scope (haven't implemented this yet).
At some point, the user may call a static method Ser::Ser2Disk (at the
moment just Ser::Ser2StdOut) that serializes all SObjects that have
registered for serialization by iterating though the serialization list,
which is a list of base class pointers. The problem is, what to do with the
base class pointers that I get off the serialization list. (I had a look at
the serialization stuff in the FAQ: the impression I got was that for
serialisation, the way suggested is to simply call each SObject's
Serialize() method... which is okay, but could be a lot better, why not with
just a single Serialize()
If I dynamic_cast the with full type information (as in `SPair<int, float>
*ptr = dynamic_cast <SPair<int, float>*> (*i);`) I get the desired derived
class, but how can I do this in a fully templated way? I suspect it may take
a drastic change in design (since SPair<int, float> is essentially a
different type than SPair<char *, double>). Any suggestions?
I guess this is an RTTI related query? (I apologise if it isn't, for the
misleading subject). I had a look at some RTTI related websites - all very
interesting, but nothing that I found to be directly helpful with my
problem. Also, according to "Dynamic Parallel Schedules framework" document
on http://dps.epfl.ch/dpsdoc/x687.htm "Simple serialization should not be
used on templated classes, since the IDENTIFY will not generate a correct
class factory in this case. Use universal serialization instead"... but the
universal serialization USAGE of that library looks daunting, I haven't even
thought about the IMPLEMENTATION yet! And anyway I don't really care about
circular structures and whatnot. So, let me basically restate what I am
trying to achieve: how to I cast a base class pointer to a templated derived
class pointer, or achieve the similar effect?
best regards,
-tirath ramdas
p/s- this looks like a toughie, so credit will be given for all lines of
code that were directly inspired by responses I get.
Code follows...
#define DEBUG // comment out to disable debugger methods
#include <iostream>
#include <list>
#include "Types.h" // for "template <class P1, class P2> class Pair"
using namespace std;
class Ser {
protected:
virtual void ser_reg()=0;
static list<Ser*> ser_list; // serialisation list
public:
#ifdef DEBUG
virtual void WhoAmI()=0;
static void Ser2StdOut(); // for debugging purposes
#endif
};
// --------------------------- S E R P A I R S ---------------------------
template <class SP1, class SP2>
class SPair: public Ser, public Pair<SP1, SP2>
{
protected:
void ser_reg() {
ser_list.push_front(this); // register for serialisation
}
public:
SPair(SP1 a, SP2 b)
air<SP1, SP2>(a,b){ // init data1, data 2
ser_reg();
cout << "\nCreated a " << typeid(this).name();
} // init Pair, and call ser_reg method
#ifdef DEBUG
void WhoAmI(){cout << "\nSER PAIR @ " << (unsigned int)(this);}
#endif
};
void Ser::Ser2StdOut()
{
list<Ser*>::const_iterator i;
for(i=ser_list.begin(); i!=ser_list.end(); i++) {
cout << endl << (unsigned int)*i << typeid(*i).name();
SPair<int, float> *ptr = dynamic_cast <SPair<int, float>*> (*i);
if(ptr!=NULL) cout << "found one!";
}
}
I have a templated class that derives from a non-templated abstract class.
How do I then cast a base class pointer to a <templated> derived class
pointer in a generalised fashion?
Here's what I'm generally trying to achieve:
I'm building (trying to anyway) a serialization library. Here's my design:
SPair<SP1, SP2> derives from Pair<P1,P2> and Ser:
Ser <___________SPair <SP1, SP2>
Pair<P1,P2> <____|
Each time a Serializable Object (SObject) is created, the ctor registers the
'this' pointer onto a serialisation list held statically in the abstract
base class (Ser); the list holds Ser* - i.e. base class pointers. Each
SObject's dtor is reponsible for removing the 'this' pointer from the list
when the object falls out of scope (haven't implemented this yet).
At some point, the user may call a static method Ser::Ser2Disk (at the
moment just Ser::Ser2StdOut) that serializes all SObjects that have
registered for serialization by iterating though the serialization list,
which is a list of base class pointers. The problem is, what to do with the
base class pointers that I get off the serialization list. (I had a look at
the serialization stuff in the FAQ: the impression I got was that for
serialisation, the way suggested is to simply call each SObject's
Serialize() method... which is okay, but could be a lot better, why not with
just a single Serialize()
If I dynamic_cast the with full type information (as in `SPair<int, float>
*ptr = dynamic_cast <SPair<int, float>*> (*i);`) I get the desired derived
class, but how can I do this in a fully templated way? I suspect it may take
a drastic change in design (since SPair<int, float> is essentially a
different type than SPair<char *, double>). Any suggestions?
I guess this is an RTTI related query? (I apologise if it isn't, for the
misleading subject). I had a look at some RTTI related websites - all very
interesting, but nothing that I found to be directly helpful with my
problem. Also, according to "Dynamic Parallel Schedules framework" document
on http://dps.epfl.ch/dpsdoc/x687.htm "Simple serialization should not be
used on templated classes, since the IDENTIFY will not generate a correct
class factory in this case. Use universal serialization instead"... but the
universal serialization USAGE of that library looks daunting, I haven't even
thought about the IMPLEMENTATION yet! And anyway I don't really care about
circular structures and whatnot. So, let me basically restate what I am
trying to achieve: how to I cast a base class pointer to a templated derived
class pointer, or achieve the similar effect?
best regards,
-tirath ramdas
p/s- this looks like a toughie, so credit will be given for all lines of
code that were directly inspired by responses I get.
Code follows...
#define DEBUG // comment out to disable debugger methods
#include <iostream>
#include <list>
#include "Types.h" // for "template <class P1, class P2> class Pair"
using namespace std;
class Ser {
protected:
virtual void ser_reg()=0;
static list<Ser*> ser_list; // serialisation list
public:
#ifdef DEBUG
virtual void WhoAmI()=0;
static void Ser2StdOut(); // for debugging purposes
#endif
};
// --------------------------- S E R P A I R S ---------------------------
template <class SP1, class SP2>
class SPair: public Ser, public Pair<SP1, SP2>
{
protected:
void ser_reg() {
ser_list.push_front(this); // register for serialisation
}
public:
SPair(SP1 a, SP2 b)
ser_reg();
cout << "\nCreated a " << typeid(this).name();
} // init Pair, and call ser_reg method
#ifdef DEBUG
void WhoAmI(){cout << "\nSER PAIR @ " << (unsigned int)(this);}
#endif
};
void Ser::Ser2StdOut()
{
list<Ser*>::const_iterator i;
for(i=ser_list.begin(); i!=ser_list.end(); i++) {
cout << endl << (unsigned int)*i << typeid(*i).name();
SPair<int, float> *ptr = dynamic_cast <SPair<int, float>*> (*i);
if(ptr!=NULL) cout << "found one!";
}
}