Static detection of class and polymorphic classes

0 views
Skip to first unread message

Anthony Williams

unread,
Feb 8, 2001, 9:02:22 PM2/8/01
to
Does anyone know of a nifty way of identifying at compile time whether a
type is of class type, and in particular of polymorphic class type?

The motivation is that I wanted to write a template class that used
dynamic_cast<void*>() to get the start address of the object, but this only
works for polymorphic class types.

Thus if I have a T*p, I want to use static_cast<void*>(p), or
dynamic_cast<void*>(p) depending on whether or not T can be used safely with
dynamic_cast.

template<typename T,bool isPolymorphic=IsPolymorphicClass<T>::result>
class StartOf{};

template<typename T,true>
{
public:
StartOf(T*):p(dynamic_cast<void*>(p)){}
void*p;
};
template<typename T,false>
{
public:
StartOf(T*):p(static_cast<void*>(p)){}
void*p;
};

For builtin types, I can specialize the template IsPolymorphicClass

template<typename T>
class IsPolymorphicClass
{
public:
enum{result=true};
};
template<typename T>
class IsPolymorphicClass<T*>
{
public:
enum{result=false};
};
class IsPolymorphicClass<int>
{
public:
enum{result=false};
};

etc.

Is there a way to do this that will also pickup classes without virtual
functions, unions and enums, without having to specialize the template for
every single UDT?

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks
The opinions expressed in this message are mine and do not represent those
of my employer

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

sieme...@my-deja.com

unread,
Feb 9, 2001, 2:08:38 PM2/9/01
to
In article <95tufq$i8g3j$1...@ID-49767.news.dfncis.de>,
"Anthony Williams" <ant...@nortelnetworks.com> wrote:

> Does anyone know of a nifty way of identifying at compile time
whether a
> type is of class type, and in particular of polymorphic class type?

Someone had posted something like this once on the newsgroup.

template <class T>
bool isPolymorphic() {
bool answer=false;
typeid(answer=true,T());
return answer;
}

If T is polymorphic, the compiler is required to evaluate the typeid
stuff at runtime, and answer will be true. If T is non-polymorphic,
the compiler is required to evaluate the typeid stuff at compile time,
whence answer will remain false. I never tried it though. And it's
not a compile time constant.


I guess if you made a class Tj derived from T and gave Tj a virtual
destructor, then you compared the sizeof(T) to sizeof(Tj) you could
maybe tell if the class is polymorphic. Most polymorphic classes have
a virtual destructor, so if T is polymorphic sizeof(T)==sizeof(Tj).
But if T has no virtual destructor, sizeof(Tj)>sizeof(T) -- which
suggests that T is non-polymorphic. It's not foolproof. Also, even if
T is polymorphic, sizeof(T)!=sizeof(Tj) may be true because the
compiler is allowed to add padding between subobjects.

> The motivation is that I wanted to write a template class that used
> dynamic_cast<void*>() to get the start address of the object, but
this only
> works for polymorphic class types.
>
> Thus if I have a T*p, I want to use static_cast<void*>(p), or
> dynamic_cast<void*>(p) depending on whether or not T can be used
safely with
> dynamic_cast.

Are you sure static_cast<void*> will have the proper effect. Suppose D
derives from B1 and B2.

D d;
B * b2=d;
void * v=static_cast<void *>(b2);

I don't think 'v' will be pointing to the full object.


--
------------
Siemel Naran


Sent via Deja.com
http://www.deja.com/

Bill Weston

unread,
Feb 19, 2001, 8:24:38 PM2/19/01
to
Anthony Williams wrote:

> Does anyone know of a nifty way of identifying at compile time whether a
> type is of class type, and in particular of polymorphic class type?
>
> The motivation is that I wanted to write a template class that used
> dynamic_cast<void*>() to get the start address of the object, but this only
> works for polymorphic class types.
>
> Thus if I have a T*p, I want to use static_cast<void*>(p), or
> dynamic_cast<void*>(p) depending on whether or not T can be used safely with
> dynamic_cast.
>

what if you define something like:

template <typename T>
struct Type {
struct Tmp : T{virtual ~Tmp(){}};
static const bool concrete = sizeof(T) != sizeof(Tmp);
};

and do your dirty work in templated classes (or functions if you have the
luxury of partial function template specialization). You could set up an
extra bool template argument and set it to:

Type<TT>::concrete (where TT is the type to be tested)

and specialise the true and false cases to do different things (ie static vs
dynamic cast) .
Only the appropriate cast should be compiled, and you're sorted!!

Hmmmmm

This trick makes the assumption that adding virtual functionality to any class
will it change its size if it was previously static, and not if it was already
dynamic, which has got to be compiler implementation dependent. So it comes
without any form of warranty ;-) and is posted in the hope that it will
irritate someone enough to post a legal solution... ...although its not
actually illegal per se, is it? So as long as it ''failed safe'' you could
use
it in any code, you would just never get the nice dynamic option if your
compiler was somehow implementing virtual functions
without vptrs??

Bill Weston w.we...@ntlworld.com

Reply all
Reply to author
Forward
0 new messages