473,750 Members | 2,186 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

templates & polymorphic classes

One problem I've come accross in designing a specific version of auto_ptr
is that I have to disntiguish between "polymorphi c" arguments and "plain" ones,
because the template has to, internally, cast to void *.

Specifically,
template <typename T> void f(T * t) {
void * p = dynamic_cast<vo id *>(t) ;
}

will not compile if T isn't of a class that has somewhere at least
a virtual function. In particular, none of the STL containers do qualify
for T.

Yet, because of multiple inheritance, if I want to get down to the base
"most" class, the dynamic_cast<vo id*> is the way to go.

I could use reinterpret_cas t instead, and this would work for all T,
except that I'd lose the "cast to base" feature mentionned above.

I could also use a pair of templates, one for polymorphic types,
and one of "POD". But I'd rather not do that.

I'd be happy with a runtime query ... if I could devise one, that is.

typeid() seems to not be applicable in this context.

Ideally, if I could come up with

template <typename T>
bool is_polymorphic( T t) {
...
}

I would be filled with joy :-)

Any taker?
--
JFB

Jul 23 '05 #1
20 2225
verec wrote:
One problem I've come accross in designing a specific version of auto_ptr
is that I have to disntiguish between "polymorphi c" arguments and "plain"
ones, because the template has to, internally, cast to void *.

Specifically,
template <typename T> void f(T * t) {
void * p = dynamic_cast<vo id *>(t) ;
}

will not compile if T isn't of a class that has somewhere at least
a virtual function.
It won't ever work, because dynamic_cast only works within a class
hierarchy, and 'void' doesn't belong to it. It doesn't seem to make much
sense to me either. How and why would you want a dynamic_cast that would
attempt to check whether an object is derived from 'void'? Why not just
static_cast?
In particular, none of the STL containers do qualify
for T.

Yet, because of multiple inheritance, if I want to get down to the base
"most" class, the dynamic_cast<vo id*> is the way to go.
No. 'void' is not the base class.
I could use reinterpret_cas t instead, and this would work for all T,
except that I'd lose the "cast to base" feature mentionned above.
I fail to see what you need that for.
I could also use a pair of templates, one for polymorphic types,
and one of "POD". But I'd rather not do that.

I'd be happy with a runtime query ... if I could devise one, that is.
What for?
typeid() seems to not be applicable in this context.

Ideally, if I could come up with

template <typename T>
bool is_polymorphic( T t) {
...
}

I would be filled with joy :-)

Any taker?


Jul 23 '05 #2
On 2005-06-16 00:26:40 +0100, Rolf Magnus <ra******@t-online.de> said:
will not compile if T isn't of a class that has somewhere at least
a virtual function.


It won't ever work, because dynamic_cast only works within a class
hierarchy, and 'void' doesn't belong to it. It doesn't seem to make much
sense to me either. How and why would you want a dynamic_cast that would
attempt to check whether an object is derived from 'void'? Why not just
static_cast?


I'm sorry I didn't make myself clear enough. An actual example will
probably help. Consider:

template <typename T> struct my_ptr {
void * rawValue ;
my_ptr(T *t) : rawValue(dynami c_cast<void *>(t)) {
}
} ;

struct polymorphic {
virtual ~polymorphic() ;
} ;

struct pod {
} ;

typedef my_ptr<polymorp hic> Poly ;
typedef my_ptr<pod> Pod ;

void
test_00005() {
Poly p(new polymorphic) ;
// Pod pp(new pod) ;
}

If I leave the "Pod pp" line commented out, everything compiles and works
fine. However, if I uncomment it, I get:
### error: cannot dynamic_cast 't' (of type 'struct pod*') to type 'void*'
### (source type is not polymorphic)

What I am after, is a way to define 'my_ptr' above so that it deals
correctly with both polymorphic and POD structs. The need for the
dynamic_cast in the case of "polymorphi c" structs is because when
MI is used, dynamic_cast guarantees that you get a pointer back to
the base object, no matter what branch of the derivation has been
used for T.

If anything is still unclear, please, let me know.

All I want is a "write once, run anywhere" (TM :-) template that I
can use all over the place, without having to ask first, "Am I dealing
with a pod or a poly?"

Many Thanks.
--
JFB

--
Do your users a favor: give them Style: http://www.uiwithstyle.org

Jul 23 '05 #3
verec wrote:
On 2005-06-16 00:26:40 +0100, Rolf Magnus <ra******@t-online.de> said:
will not compile if T isn't of a class that has somewhere at least
a virtual function.

It won't ever work, because dynamic_cast only works within a class
hierarchy, and 'void' doesn't belong to it. It doesn't seem to make much
sense to me either. How and why would you want a dynamic_cast that would
attempt to check whether an object is derived from 'void'? Why not just
static_cast?

I'm sorry I didn't make myself clear enough. An actual example will
probably help. Consider:

template <typename T> struct my_ptr {
void * rawValue ;
my_ptr(T *t) : rawValue(dynami c_cast<void *>(t)) {


There is no need to use 'dynamic_cast' to convert a pointer to an object
to void*. It's convertible _implicitly_.
}
} ;

struct polymorphic {
virtual ~polymorphic() ;
} ;

struct pod {
} ;

typedef my_ptr<polymorp hic> Poly ;
typedef my_ptr<pod> Pod ;

void
test_00005() {
Poly p(new polymorphic) ;
// Pod pp(new pod) ;
}

If I leave the "Pod pp" line commented out, everything compiles and works
fine. However, if I uncomment it, I get:
### error: cannot dynamic_cast 't' (of type 'struct pod*') to type 'void*'
### (source type is not polymorphic)

What I am after, is a way to define 'my_ptr' above so that it deals
correctly with both polymorphic and POD structs. The need for the
dynamic_cast in the case of "polymorphi c" structs is because when
MI is used, dynamic_cast guarantees that you get a pointer back to
the base object, no matter what branch of the derivation has been
used for T.
To what base object? The pointer you store is 'void*'!
If anything is still unclear, please, let me know.
Hell, yes. Perhaps you could post the _real_ 'my_ptr' class.
All I want is a "write once, run anywhere" (TM :-) template that I
can use all over the place, without having to ask first, "Am I dealing
with a pod or a poly?"


You should also try to show _how_ you're going to use an object of type
'my_ptr'. "I can use all over the place" is too vague a statement to be
of any value.

V
Jul 23 '05 #4
On 2005-06-16 22:43:49 +0100, Victor Bazarov <v.********@com Acast.net> said:
template <typename T> struct my_ptr {
void * rawValue ;
my_ptr(T *t) : rawValue(dynami c_cast<void *>(t)) {


There is no need to use 'dynamic_cast' to convert a pointer to an object
to void*. It's convertible _implicitly_.


Excellent! I just tried. And it works!

Many Thanks.
--
JFB

Jul 23 '05 #5
On 2005-06-16 22:43:49 +0100, Victor Bazarov <v.********@com Acast.net> said:
There is no need to use 'dynamic_cast' to convert a pointer to an object
to void*. It's convertible _implicitly_.


Browsing Google a bit harder, I stumbled accross:

http://groups-beta.google.com/group/...b20c6aa38940c9

Which

means now I'm not too sure what to think :(

--
Do your users a favor: give them Style: http://www.uiwithstyle.org

Jul 23 '05 #6
[]
There is no need to use 'dynamic_cast' to convert a pointer to an object
to void*. It's convertible _implicitly_. [] To what base object? The pointer you store is 'void*'!


Actually he got it wrong, but not completely:

/dynamic_cast < type-id > ( expression )/
....
/If type-id is void*, a run-time check is made to determine the/
/actual type of expression. The result is a pointer to the complete/
/object pointed to by expression./

So dynamic_cast to "void*" is a distinct language feature.

The point is, that the _value_ of that "void*" will be
comparable wherever the original pointer was cast' from. Which IMHO
can be a handy feature.
Jul 23 '05 #7
> Ideally, if I could come up with

template <typename T>
bool is_polymorphic( T t) {
...
}

I would be filled with joy :-)

Any taker?
--
JFB


::boost::is_pol ymorphic<T>::va lue

Look here: http://www.boost.org/libs/type_traits/index.html

The only problem is that the implementation of
::boost::is_pol ymorphic is basically a hack that relies on
the compiler inserting a vtable-pointer into a polymorphic class,
(and thereby adding to it's size).
Appearently it works with most compilers, but it's way outside
the C++ standard, and there's no guarantee that it will work
as expected under any circumstances or with new versions/revisions
of any compiler you may use today.

But since most boost developers tend to be nifty & smart guys I
think it might be the best way to do it. Which does not mean I'd
use it, but I think chances of finding some better solution are
rather slim.

Of course there might be a better runtime solution - since
::boost::is_pol ymorphic<T>::va lue is a compile-time solution. But
then again, what would you do if you have that information at runtime?
If it's a runtime solution you have to have that dynamic_cast
from T to void* somewhere in your program ... even if it would never
be called if T is not polymorphic it's still there and it won't
compile :-(

Or did I miss something?

BTW: dynamic_cast<vo id*>() will yield the address of the _complete_
object which could be considered the exact opposite of the "most base
type" thing you mentioned.
And: "POD" is not the opposite of "polymorphi c" since there are plenty
types that aren't "POD" but aren't "polymorphi c" either. E.g.:

struct X { X(); int x; };

is _not_ a POD since it defines a constructor.
Jul 23 '05 #8
On 2005-06-17 02:52:13 +0100, Swampmonster
<sw**********@d er-ball-ist-rund.net> said:
::boost::is_pol ymorphic<T>::va lue

Look here: http://www.boost.org/libs/type_traits/index.html
Good news.
BTW: dynamic_cast<vo id*>() will yield the address of the _complete_
object which could be considered the exact opposite of the "most base
type" thing you mentioned.
Sorry to have been misleading. What you just said is what I meant,
what I wrote is ... what you understood anyway :-)
And: "POD" is not the opposite of "polymorphi c" since there are plenty
types that aren't "POD" but aren't "polymorphi c" either. E.g.:

struct X { X(); int x; };

is _not_ a POD since it defines a constructor.


I shall stand corrected!

My apologies for my sloppy choice of words :(

OK. The summary, as I see now is:

- there is a way to get at the "outer-most" or "complete" object
using dynamic_cast<vo id *>(T)

- the "implicit conversion to void *" mentionned by Victor does
indeed exist, but does not offer that guarantee. Whether this
implicit cast to void * is equivalent to reinterpret_cas t<void *>(T)
is still to be determined, but seems the most logical choice

- There is at least one answer to my problem in the form of
::boost::is_pol ymorphic<T>::va lue

Many Thanks.
--
JFB

Jul 23 '05 #9
Funny how a single byte can change things ...

It turns out that I got my condition wrong, and set value to non-zero,
meaning: "monomorphi c" with the opposite test to what was required.

Once I had changed the != into a ==, as it was meant to be, everything
compiles and runs, and, stepping with the debugger I can see either
reinterpret_cas t or dynamic_cast being invoked as I expect them to!

Many thanks!

template <typename T> struct is_polymorphic {
struct T1 : public T {
virtual ~T1() {}
} ;

enum { // ooops! wrote != the first time through ...
value = sizeof(T1) == sizeof(T)
} ;
} ;

template <int I, typename T> struct void_star_caste r {
static void * cast(T * t) {
return dynamic_cast<vo id *>(t) ;
}
} ;
template <typename T> struct void_star_caste r<0, T> {
static void * cast(T * t) {
return reinterpret_cas t<void *>(t) ;
}
} ;

template <typename T> struct my_ptr {

void * rawValue ;

typedef void_star_caste r<is_polymorphi c<T>::value, T> caster ;
my_ptr(T *t) : rawValue(caster ::cast(t)) {

}

} ;

struct polymorphic {

virtual ~polymorphic() ;

} ;

polymorphic::~p olymorphic() {}

struct monomorphic {

} ;

typedef my_ptr<polymorp hic> Poly ;

typedef my_ptr<monomorp hic> Mono ;

void

test_00005() {

Poly p(new polymorphic) ;
Mono m(new monomorphic) ;

}

--
JFB

Jul 23 '05 #10

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

Similar topics

1
2568
by: Vince C. | last post by:
Hi all, I've created XML documents that are described with a schema. I'm using those documents to create web pages. All my web pages contain a fixed header and a variable document part. The header is the same in each page and is described in an XML document, "Head.xml". The document part, which is variable in content, is described in other XML files (e.g. "Document.xml", "Product.xml", "Register.xml").
1
1185
by: Kai-Uwe Bux | last post by:
Hi, I have determined that replacing T* by pointer_to<T> is a good idea: (a) If the template signature is actually template < typename T, typename Alloc=some_standard_allocator<T> > class pointer_to { ...
7
3914
by: Mr. Ed | last post by:
I have a base class which has about 150 derived classes. Most of the derived classes are very similar, and many don't change the base class at all. All the derived classes have a unique factory method which returns a new object of the derived type. The problem I've got is that I now need to polymorphically clone a derived class object, but I don't want to write a separate 'clone' method for each of these 150 classes. Instead, I thought I...
27
2154
by: Chad | last post by:
The problem is: Write a recursive version of the function reverse(s), which reverses the string s in place. In "The C Answer Book", Second Edition, near the bottom of page 95, the authors say "This is not a good application of recursion". Just for the record, I did make an attempt at the solution before I broke down and looked at the solution in the book.
2
3389
by: sarathy | last post by:
Hi all, I need a small clarification reg. Templates and Polymorphism. I believe templates is really a good feature, which can be used to implement generic functions and classes. But i doubt whether it should not be used in certain cases. Consider the case when all the params to a template function/class are similar. My questions is that whatever can be acheived by a template in such a case, can be acheived by runtime polymorphism....
11
3051
by: toton | last post by:
Hi, I have little confusion about static memory allocation & dynamic allocation for a cluss member. I have class like class Bar{ public: explicit Bar(){ cout<<"bar default"<<endl; }
23
2598
by: Ben Voigt | last post by:
I have a POD type with a private destructor. There are a whole hierarchy of derived POD types, all meant to be freed using a public member function Destroy in the base class. I get warning C4624. I read the description, decided that it's exactly what I want, and ignored the warning. Now I'm trying to inherit using a template. Instead of "destructor could not be generated because a base class destructor is inaccessible", I now have an...
16
1854
by: chameleon | last post by:
I have 2 classes with exactly the same members (all static except dtor/ctor). Classes have different implementantion in only one static member function and first class has one more member function. How can I write this code with templates? First of all: Thought to write code with templates is correct? members of classes are static because refer to devices. There is no reason to be non-static.
5
2042
by: Zeppe | last post by:
Hi all! my problem is this one, I think that it could be a common one, maybe a pattern, so if you can help me somehow it would be great. Let's suppose I have a class Base class Base { // impl. };
0
8836
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9575
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9394
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9338
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9256
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6080
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4712
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
2798
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2223
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.