Re: casting (void *) to (class *)
* James Kanze:
On Apr 15, 4:04 am, "Alf P. Steinbach" <al...@start.no> wrote:
* 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?
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.
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.
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.
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...
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
--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :-) Just going there is good. Linking
to it is even better! Thanks in advance!