casting (void *) to (class *)

J

Jonathan Lee

Hello all,
Can someone tell me what the best way is to cast a void* to a class
pointer? I'm currently using reinterpret_cast<ClassName *>
(myvoidpointer) and I'd prefer not to. But dynamic_cast<> complains
that void* isn't a class pointer. And static_cast<> doesn't seem right
either... I'd like run time checking. Of course, if reinterpret_cast
is the only way, I'll live with it.

For context, it's for a "thread" class with pthreads backing it. I
know that the void* was originally a pointer to the class and it is
merely being restored to the correct type (it's just the _this_
pointer being mangled by pthread_create).
--Jonathan
 
A

Alf P. Steinbach

* Jonathan Lee:
Hello all,
Can someone tell me what the best way is to cast a void* to a class
pointer? I'm currently using reinterpret_cast<ClassName *>
(myvoidpointer) and I'd prefer not to. But dynamic_cast<> complains
that void* isn't a class pointer. And static_cast<> doesn't seem right
either... I'd like run time checking. Of course, if reinterpret_cast
is the only way, I'll live with it.

I suggest doing the opposite of how you obtained the void* in the first place;
that seems logical.

But better, don't use void* pointers (except for the special case of identifying
objects in e.g. a hash table, in which case you should make sure to have
pointers to complete objects, e.g. obtained by dynamic_cast to void*).

However, void* may be practically necessary in the context of a C code callback.

For context, it's for a "thread" class with pthreads backing it. I
know that the void* was originally a pointer to the class and it is
merely being restored to the correct type (it's just the _this_
pointer being mangled by pthread_create).

There is a good chance that the original pointer was just implicitly converted
to void*, in which case the conversion was equivalent to a static_cast, which is
then what you should do to get back the original.

But consider using Boost threads.

AFAIK they're based on pthreads, but offering a more type safe C++ interface,
and in addition, will be part of C++0x so using them is preparing for the future...


Cheers & hth.,

- Alf
 
J

Jonathan Lee

Alf,
I suggest doing the opposite of how you obtained the void* in the first place;
that seems logical.

When you put it that way it all seems so obvious.
However, void* may be practically necessary in the context of a C code callback.

Yeah.. don't want to use void*, but that's exactly the situation I'm
in.
But consider using Boost threads.
...
and in addition, will be part of C++0x so using them is preparing for the future...

Thanks for the heads up; I didn't know this. Boost is probably
overkill for my needs, but you're absolutely right about preparing for
the future.

--Jonathan
 
V

Vladimir Jovic

Alf said:
There is a good chance that the original pointer was just implicitly
converted to void*, in which case the conversion was equivalent to a
static_cast, which is then what you should do to get back the original.

This is the second time I see someone is using static_cast to cast
pointers. I thought that the reinterpret_cast should be used, no?
 
J

James Kanze

This is the second time I see someone is using static_cast to
cast pointers. I thought that the reinterpret_cast should be
used, no?

In the general case, the semantics are not the same; you should
use the cast with the semantics you need (which except in the
lowest levels of coding, things like implementing memory
allocators, should be static_cast).

In the case of to and from void*, the semantics between
static_cast and reinterpret_cast are the same, as far as the
language and the compiler are concerned. As far as the reader
is concerned, however, Alf said it exactly---use whatever was
(logically) used to get the void* in the first place, which in
most cases will be static_cast.
 
J

James Kanze

* Jonathan Lee:
But better, don't use void* pointers (except for the special
case of identifying objects in e.g. a hash table, in which
case you should make sure to have pointers to complete
objects, e.g. obtained by dynamic_cast to void*).

I'm not sure I understand this one. Do you mean just using the
pointer as the key? (And how do you get a hash value for a
pointer, portably?)
However, void* may be practically necessary in the context of
a C code callback.

Yes, and you can encounter a similar problem to the above.
About the only legal thing you can do with a void* is cast it
back to the original type (and only that type) before using it.
(You can, of course, copy it and compare it.) Thus, the
following is undefined behavior:

Derived* p1 = new Derived ;
void* p2 = p1 ;
Base* p3 = static_cast< Base* >( p2 ) ;
p3 -> ...

The second line must be written:
void* p2 = static_cast< Base* >( p1 ) ;
for the rest to work.

(This often happens in callback contexts, e.g. pthread_create or
CreateThread, where the called function does something like:

void*
newThread( void* p )
{
static_cast< Base* >( p )->run() ;
}

Passing the address of this function and a pointer to a derived
type to pthread_create or CreateThread will cause undefined
behavior.)
There is a good chance that the original pointer was just
implicitly converted to void*, in which case the conversion
was equivalent to a static_cast, which is then what you should
do to get back the original.
But consider using Boost threads.
AFAIK they're based on pthreads, but offering a more type safe
C++ interface, and in addition, will be part of C++0x so using
them is preparing for the future...

Actually, this is one place where the standard did evolve
significantly from Boost: the thread and its identifier have
been separated, there is an explicit function for detach
(although the implicit detach in the constructor is still
there, rather than having it an error condition to destruct a
joinable thread), and of course, the standard type makes use of
new standard features, like rvalue references and move
semantics.

Of course, it still fails to make detached and joinable threads
two distinct types---in fact, there's no need for a "type" for
detached threads, just a function to start them, and you
typically don't want copy or move semantics for the constructor
arguments for a joinable thread. Using the same basic interface
for both means we have a compromize. Depending on the use, the
use of copy semantics may make starting a joinable thread much
more expensive than necessary---this is certainly the case for
Boost, at any rate. I'm not sure how move semantics interact
with threads, so I can't say too much about the impact there.
 
A

alasham.said

Hello,

reinterpret_cast has the same semantics as explicit C-type cast, and
is used to convert between unrelated types having the same bit
pattern. More secure pointer conversions are handled by static_cast,
or dynamic_cast (when RTTI support is nedded, such as for down-cast).

Regards
 
A

Alf P. Steinbach

* James Kanze:
I'm not sure I understand this one. Do you mean just using the
pointer as the key?
Yes.


(And how do you get a hash value for a pointer, portably?)

Wait a sec, checking Boost...

KO.


// Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const& v)
#else
template <class T> std::size_t hash_value(T* v)
#endif
{
std::size_t x = static_cast<std::size_t>(
reinterpret_cast<std::ptrdiff_t>(v));

return x + (x >> 3);
}


Then reduction to the internally required range of the particular hash table is
the responsibility of that hash table.

Yes, and you can encounter a similar problem to the above.

Some context must have disappeared here.

About the only legal thing you can do with a void* is cast it
back to the original type (and only that type) before using it.
(You can, of course, copy it and compare it.)

And you can cast from POD* to FirstMember*.

Or the other way.

Thus, the
following is undefined behavior:

Derived* p1 = new Derived ;
void* p2 = p1 ;
Base* p3 = static_cast< Base* >( p2 ) ;
p3 -> ...

The second line must be written:
void* p2 = static_cast< Base* >( p1 ) ;
for the rest to work.

(This often happens in callback contexts, e.g. pthread_create or
CreateThread, where the called function does something like:

void*
newThread( void* p )
{
static_cast< Base* >( p )->run() ;
}

Passing the address of this function and a pointer to a derived
type to pthread_create or CreateThread will cause undefined
behavior.)

Isn't it fun.

Actually, this is one place where the standard did evolve
significantly from Boost: the thread and its identifier have
been separated,
Ouch.


there is an explicit function for detach
(although the implicit detach in the constructor is still
there, rather than having it an error condition to destruct a
joinable thread), and of course, the standard type makes use of
new standard features, like rvalue references and move
semantics.

Do the C++0x threads require use of the rvalue stuff?

That is, have they re-designed the threads so that they break existing code and
can't be reasonably implemented in C++98?

Of course, it still fails to make detached and joinable threads
two distinct types

What do you mean by "detached thread"?

---in fact, there's no need for a "type" for
detached threads, just a function to start them, and you
typically don't want copy or move semantics for the constructor
arguments for a joinable thread. Using the same basic interface
for both means we have a compromize. Depending on the use, the
use of copy semantics may make starting a joinable thread much
more expensive than necessary---this is certainly the case for
Boost, at any rate. I'm not sure how move semantics interact
with threads, so I can't say too much about the impact there.

Uh, are you saying that someone is seriously considering /copying/ threads?


Cheers,

- Alf
 
M

Maxim Yegorushkin

reinterpret_cast has the same semantics as explicit C-type cast,

Not true.

Semantics of a C-style cast in C++ depends on the argument and the
destination type. See 5.4.4:
<q>
The conversions performed by

— a const_cast (5.2.11),
— a static_cast (5.2.9),
— a static_cast followed by a const_cast,
— a reinterpret_cast (5.2.10), or
— a reinterpret_cast followed by a const_cast,

can be performed using the cast notation of explicit type conversion.
The same semantic restrictions and behaviors apply. If a conversion
can be interpreted in more than one of the ways listed above, the
interpretation that appears first in the list is used, even if a cast
resulting from that interpretation is ill-formed.
</q>

Here in particular, the semantics of a C-style cast of void* to T* are
exactly that of a static_cast said:
and is used to convert between unrelated types having the same bit
pattern. More secure pointer conversions are handled by  static_cast,
or dynamic_cast (when RTTI support is nedded, such as for down-cast).

Does not apply in this case.
 
M

Maxim Yegorushkin

Alf,


When you put it that way it all seems so obvious.


Yeah.. don't want to use void*, but that's exactly the situation I'm
in.

You can easily create a C++ functor to a C-style callback adaptor.
Example:

// the C-style callback
typedef void recordCb(
void* cb_data
, unsigned long record_id
, char const* record
, unsigned long record_len
);
// reads [from, to] records and return the number of records
actually read,
// i.e. can read less than requested.
unsigned long readRecords(unsigned long from, unsigned long to,
recordCb* cb, void* cb_data);

// functor to c-style callback adaptor
template<class Functor>
unsigned long readRecords(unsigned long from, unsigned long to,
Functor f);
{
struct Trampoline
{
static void cb(
void* cb_data
, unsigned long record_id
, char const* record
, unsigned long record_len
)
{
(*static_cast<Functor*>(cb_data))(record_id, record,
record_len);
}
};

return readRecords(from, to, Trampoline::cb, &f);
}
 
J

Jonathan Lee

The second line must be written:
    void*    p2 = static_cast< Base* >( p1 ) ;
for the rest to work.

Actually, I was wondering about this last night. I _am_ using a Base
and Derived class, where the Base class is responsible for creating
the thread. The value it converts to void* and passes to pthread_create
() is the _this_ pointer. But where does _this_ point to? I'm
interfacing the function through the Derived object, so does it point
to a class of type Derived. Or will it point to the class of type
Base? I'm assuming the latter because how else could you use _this_
consistently?

I didn't find anything on the 'net that was unambiguous.

It's also my understanding that if I use dynamic_cast<void *>(this)
I'll get a pointer to the most derived class. So this in particular
won't restore to the right pointer, will it? (and I do have virtual
functions to consider) I'll have to use static_cast<> to cast to
void*, then.

Now combined with the opening question: do I first have to do
static_cast<Base *>(this) before static_cast<void*>(that)?
 
M

Maxim Yegorushkin

* James Kanze:



Wait a sec, checking Boost...

KO.

    // Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
     template <class T> std::size_t hash_value(T* const& v)
#else
     template <class T> std::size_t hash_value(T* v)
#endif
     {
         std::size_t x = static_cast<std::size_t>(
            reinterpret_cast<std::ptrdiff_t>(v));

         return x + (x >> 3);
     }

Wow! Why can't it be as simple as:

std::size_t x = v - static_cast<T*>(0);

?
 
A

Alf P. Steinbach

* Maxim Yegorushkin:
Wow! Why can't it be as simple as:

std::size_t x = v - static_cast<T*>(0);

?

Because the subtraction is only formally defined when the '-' operands are both
pointers within the same array (including hypothetical after-end element) or,
uh, I'm too lazy to look it up, but roughly, point to the same object or within
the same POD object.

The standard library's comparision functors do magic that implies that they're
somehow accessing a linear ordering of pointer values, but AFAIK that is not
exposed for use by ordinary programmers, so one is reduced to casting.

On the other hand, I don't know why the Boost developers add x/8.


Cheers & hth.,

- Alf
 
M

Maxim Yegorushkin

Because pointer arithmetic is only defined for pointers to objects in
the same array (or one past the end of the array).

True.

Actually, the original code casts a pointer to an integer, whereas
what I posted is doing a different thing (count of objects).
 
J

James Kanze

* James Kanze:
Wait a sec, checking Boost...

// Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const& v)
#else
template <class T> std::size_t hash_value(T* v)
#endif
{
std::size_t x = static_cast<std::size_t>(
reinterpret_cast<std::ptrdiff_t>(v));
return x + (x >> 3);
}
Then reduction to the internally required range of the
particular hash table is the responsibility of that hash
table.

Of course. But the above isn't guaranteed to work, and I've
worked on systems where it wouldn't work. (By not working, I
mean that two pointers which compare equal will result in
different hash values.) I also know of one system where it is
almost useless. Where for any dynamically allocated complete
object, x would always have the same value. The above supposes
a one to one mapping between pointers and the integral types
involved, which is far from universal.

I also don't see why the double cast, rather than casting
directly to size_t, and the expression in the return statement
is a hack. If they're willing to restrict the function to
architectures with a one to one mapping, then they might as well
restrict it to architectures without any padding bits in
integral types as well, and just do a classical hash treating
the pointer as an array of bytes.
Some context must have disappeared here.

Maybe. I think you mentionned something about having to be sure
that the void* was obtained from the complete object, and not by
e.g. a static_cast of a pointer to a base class. The problem
being that converting pointers to different base classes of an
object may result in different void*. The problem with
callbacks is basically the same: a void* obtained by converting
from the address of the complete object may not be the same as
one obtained by converting from a pointer to a base class.
And you can cast from POD* to FirstMember*.
Or the other way.

Yes. It's highly unlikely that POD or FirstMember have type
void. But I think you can go through a void* in those
conversions. (I'm not sure that the standard guarantees it, but
in practice, you surely can, given that the conversion without
passing through void* is legal, and converting to void* and back
to the original type must work.)
Isn't it fun.

Especially because in practice, the erroneous code works in a
lot of cases. Until some change in an apparently unrelated part
(addition of a second base class to Derived, for example) causes
it to break.

Ouch in what sense? That you've got a lot of code using Boost,
and that converting it to the standard will be a lot of work?

The reasonning behind this is simple (sort of): a thread, per
se, has identity, and shouldn't be copiable (although the
standard version is movable). A thread identifier, however,
should be copiable, so it can be used in standard containers.
Do the C++0x threads require use of the rvalue stuff?

I don't think they require it. I imagine that there are some
cases where it might be useful, however. If nothing else, it
allows you to create a thread in a function and return it, so
that the calling code can do the join. Without movability
(which supposes rvalue references), you'd have to allocate it
dynamically, or give up identity, both of which have other
problems.
That is, have they re-designed the threads so that they break
existing code and can't be reasonably implemented in C++98?

Well, they can't break existing code, because no existing code
uses std::thread. And most of the library in the new standard
can't be implemented in C++98, because there are rvalue
references everywhere. (And of course, you can't implement
anything which uses threads in C++98:). But I know what you
mean.) On the other hand, you should be able to implement most
of the interface in C98, with the exception of the movability
stuff.
What do you mean by "detached thread"?

One that can't be joined. Under Unix, one on which you've
called pthread_detach. Under Windows (I think), one on which
you've closed all handles to it. In other words, the opposite
of a joinable thread.
Uh, are you saying that someone is seriously considering
/copying/ threads?

Not the object of thread type. But a thread executes code: in
C++, a functional object. And that gets copied (at least in
Boost). And that copy must occur in a thread safe manner; you
can't return from starting the thread (the constructor of thread
in the case of Boost and std::thread) before the copy has
finished, in the newly started thread. Which means (at least in
the case of Boost---there may be other solutions, but I'm not
familiar with them) an additional condition variable, and a
wait.

In the case of a joinable thread, this is typically not what is
wanted; the functional object will remain alive (but untouched
by the original thread) until after the join has finished, at
which time, the original thread will access the data in the
functional object which was modified by the joined thread. In
practice, the copy isn't a big problem; you just add a level of
indirection in the functional object (which contains a pointer
to the data object, rather than the data itself). But the extra
synchronization may have a performance impact on some systems,
e.g. in cases where threading is being used to parallelize
operations on a multi processor system.
 
J

James Kanze

Wow! Why can't it be as simple as:

std::size_t x = v - static_cast<T*>(0);

Because the subtraction isn't defined. On the other hand, it
could be as simple as:
std::size_t x = reinterpret_cast< std::size_t >( v ) ;
I don't see what the extra cast changes. Of course, neither
that nor the original work portably. In fact, they're not even
guaranteed to compile, and if they do, they may result in two
pointers which compare equal having different hash values.

Your suggestion contains undefined behavior, but on the whole,
is probably more robust than the original code in practice. I
can see it giving the same value for all dynamically allocated
objects on some systems, but I can't imagine a real case where
it would give different hash values to pointers which compare
equal.
 
J

James Kanze

* Maxim Yegorushkin:
On the other hand, I don't know why the Boost developers add x/8.

That one's easy. All of the pointers to dynamically allocated
memory, and most other pointers as well, will be aligned. Which
mean that the low order bits will be zero. Adding x/8 is a
feeble attempt at shuffling, to avoid this.

Given the other assumptions necessary for there solution to
work, they'd be better off just casting the address of the
pointer to char*, and using the standard hashing algorithm (e.g.
of a string).
 
J

James Kanze

Actually, the original code casts a pointer to an integer,
whereas what I posted is doing a different thing (count of
objects).

Which, of course, fails at compile time if the integral type is
not large enough to hold it. Arguably, on most machines, the
cast to ptrdiff_t should fail (if pointer values are considered
"positive"), since by definition, it won't be large enough. On
a segmented architecture, the conversion to size_t might not
compile either, since size_t might not provide enough room for
the segment. And any number of architectures, different bit
patterns may address the same memory---comparison of pointers
must take this into account, but the conversion to an integral
type may preserve the bit pattern, and comparison of the
resulting integers may take the bits into consideration.
 
J

James Kanze

Actually, I was wondering about this last night. I _am_ using
a Base and Derived class, where the Base class is responsible
for creating the thread. The value it converts to void* and
passes to pthread_create () is the _this_ pointer. But where
does _this_ point to?

The type of this is *always* T* (or T const*) in a function
member of T. Regardless of the most derived type of the object.
And as a T*, it points to a T, regardless of the most derived
type.
I'm interfacing the function through the Derived object, so
does it point to a class of type Derived. Or will it point to
the class of type Base? I'm assuming the latter because how
else could you use _this_ consistently?

You couldn't.
I didn't find anything on the 'net that was unambiguous.
It's also my understanding that if I use dynamic_cast<void
*>(this) I'll get a pointer to the most derived class. So this
in particular won't restore to the right pointer, will it?
(and I do have virtual functions to consider) I'll have to use
static_cast<> to cast to void*, then.

Yes. Whatever you do, don't use dynamic_cast to void*. Almost
by definition, what it gives you isn't usable, at least as a
pointer. (As Alf suggested, it could be used as a unique id of
the object, e.g. as a key in std::map.) To use it, you have to
convert it back to the most derived type, which, of course, you
don't know.
Now combined with the opening question: do I first have to do
static_cast<Base *>(this) before static_cast<void*>(that)?

If you are in a function of Base, the this has the type Base*,
so that static_cast isn't necessary. Elsewhere, it is. And I'd
leave the conversion to void* implicit (but that's really a
style question).
 
A

Alf P. Steinbach

* James Kanze:
Of course. But the above isn't guaranteed to work, and I've
worked on systems where it wouldn't work. (By not working, I
mean that two pointers which compare equal will result in
different hash values.)

I think that problem is academic.

It is the problem of a platform not supporting Boost. :)

If one could find a C++ compiler for 16-bit Windows or MS-DOS and compile in
anything but "large model" there would be a problem. Actually I still have the
CD for such a compiler, Visual C++ 1.5 :) But it's not standard C++.

We can *imagine* some embedded system using e.g. an 80286 or something, and
segemented addressing.

But it's a myth that standard C++ is applicable to such systems.

I also know of one system where it is
almost useless. Where for any dynamically allocated complete
object, x would always have the same value.

The standard guarantees roundtrip conversion for integer of "sufficient size".

So when the integer is of "sufficient size" conversion to integer can't yield
the same value for different pointer values.

The above supposes
a one to one mapping between pointers and the integral types
involved, which is far from universal.

It can only be far from universal if there are a number of systems with C++
compilers where those integer types, ptrdiff_t and size_t, are not of the
"sufficient size" required by the standard for roundtrip conversion.


I also don't see why the double cast, rather than casting
directly to size_t,

Me neither.

If anything, perhaps it is designed to encourage discussion about why the heck
they're doing that. :)

But there is a difference, namely that for a sign-and-value representation of
signed integers, it maps binary 00...0 and 10...0 to the same size_t value, 0.

and the expression in the return statement is a hack.

Sort of. A maximum alignment of 8 is pretty universal. And it's only a "value
adding service" so to speak, for the hashing can't guarantee lack of collisions
in the final reduction to hast table size; it can only make it less likely.

If they're willing to restrict the function to
architectures with a one to one mapping, then they might as well
restrict it to architectures without any padding bits in
integral types as well, and just do a classical hash treating
the pointer as an array of bytes.

Well, they're relying on the guaranteed roundtrip conversion for "sufficient
size" integers, which means guaranteed unique values.

As I see it. :)


Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top