473,396 Members | 2,089 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

[RTTI] cast base class pointer to <templated> derived class pointer

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):Pair<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!";
}
}
Jul 19 '05 #1
3 6547
"tirath" <in****@xsmail.com> wrote in message
news:3f******@news.comindico.com.au...
....
I'm building (trying to anyway) a serialization library. Here's my design:

SPair<SP1, SP2> derives from Pair<P1,P2> and Ser: .... the list holds Ser* - i.e. base class pointers. .... 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()
What do you mean by a 'single' Serialize() ?
AFAICT, different code needs to be generated for each template instance
of SPair that is used in your program. (If not, please clarify...).
The easiest way to generated these multiple Serialize() routines is to
make Serialize() a member function of the SPair template.

Then you still need a mechanism to access the Serialize() routine
that matches the object instance you currently have a reference to.
The native C++ way of doing this is to use a virtual method
declared in the base class.

Therefore:
in class Ser:
virtual void Serialize(_some_params_)=0;

in template class SPair:
virtual void Serialize(_some_params_)
{ /* code to serialize each member of the pair */ }
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?


Is there a reason why you do not want to consider a virtual method ?

There are contorted ways to avoid using this simple and efficent
approach (see "Modern C++ Design" to see how sophisticated things
can become). But it is unclear to me why you do not want to use it here.
Regards,
Ivan
--
http://ivan.vecerina.com
Jul 19 '05 #2
> Therefore:
in class Ser:
virtual void Serialize(_some_params_)=0;

in template class SPair:
virtual void Serialize(_some_params_)
{ /* code to serialize each member of the pair */ }
Is there a reason why you do not want to consider a virtual method ?


Not at all... pure ignorance on my part! I was under the impression that
with a base class pointer you can ONLY get access to base class methods,
even if the method was virtual (I thought virtual was just to allow a base
class method to be overridden by a derived class' version). And anyway I
could've sworn I tried it but it didn't work... the perils of writing C++
too early in the morning/too late in the night!

For UNserialization I think I will still need a fair bit of thinking to
tackle the issue of templated types... or maybe theres something simple that
I've misunderstood/overlooked, as has now again been proven to occur.

Thanks very much Ivan.
Jul 19 '05 #3
Hi tirath,
For UNserialization I think I will still need a fair bit of thinking to
tackle the issue of templated types... or maybe theres something simple that I've misunderstood/overlooked, as has now again been proven to occur.


The typical solution is pretty much the one described in the FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-35.8

One function template you might find useful is something like:
template<class T>
Ser* SerCreate( istream src )
{ return new T(src); }

You could rely on a map like the following to retrieve
the factory function of each individual type:

typedef Ser* (*SerCreatorF)( istream src );

typedef std::map< std::string, SerCreatorF > SerCreatorsMap;
SerCreatorsMap serCreators; // global var

Each unserializable type then needs to be registered with
something like:
template<class T>
void RegisterSer(std::string const& typeId)
{
SerCreatorF creatorFunc = &SerCreate<T>;
serCreators["pair_int_float"] = creatorFunc;
}

Register each type with something like:
RegisterSer<SPair<int,float> >("pair_int_float");

NB: It would be tempting to use the compiler-generated type
name that can be obtained with typeid(SomeType).name(),
but this is unfortunately not portable.

And, during unserialization, retrieve the polymorphic
objects with something like:
Ser* loadSerObject(istream src)
{
std::string typeID;
src>> typeID;
SerCreatorsMap::const_iterator pos = serCreators.find(typeID);
if( pos == serCreators.end() )
throw "UNKNOWN TYPE";

return (pos->second)(src);
}

Regards,
Ivan
--
http://ivan.vecerina.com

Jul 19 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

25
by: John Harrison | last post by:
This code fails to compile on Comeau C++ and VC++ 7.1 (with language extensions disabled) template <class T> struct B { T b; }; template <class T>
1
by: Art | last post by:
This is partially an academic question, but I'm trying to understand templates better. I have a base class that uses template parameters to define the behavior of its class. I want to subclass this...
2
by: ferdinand.stefanus | last post by:
Hi, I have some questions regarding templated class constructor: #include <iostream> using namespace std; template<typename T> class Foo { public:
9
by: Jon Wilson | last post by:
I have a class which needs to accumulate data. The way we get this data is by calling a member function which returns float on a number of different objects of different type (they are all the...
4
by: Lionel B | last post by:
Greetings, The following code: <code> template<typename T> class A { protected:
5
by: Gert Van den Eynde | last post by:
Hi all, It's probably trivial but I can't figure it out... I have a templated class template <typename T, typename uclass A I wish to fill a vector with pointers to objects of class A. I...
2
by: m.tyka | last post by:
Hello, I have the following code --- template < typename T> struct Base { T base_member; };
2
by: mosfet | last post by:
Hi, I have qome questions about templated class and pointer. Let's says I have some graphical classes defined like this(WTL framework) : // represent a view class CFooView : public...
4
by: David Sanders | last post by:
Hi, I have a class depending on a template parameter: template<int n> class MyClass { }; I want the template parameter to be chosen according to a variable, e.g.
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.