Best way to cast anythign to void* and back

  • Thread starter christopher diggins
  • Start date
C

christopher diggins

Hello,

I want to convert a value of type T where sizeof(T) <= sizeof(void*) into a
void* and back again. I am currently doing it as follows:

void** ppvoid = reinterpret_cast<void**>(const_cast<T*>(&x));
void* x = *ppvoid;

This works on Visual C++ and GCC 3.4 but I suspect it is not the "correct"
way to do things.

I considered the union approach:

template<typename T>
union cast_union {
void* pvoid;
T x;
}

But this doesn't work because T might have non-trivial constructors.

Any help would be most appreciated.
 
V

Victor Bazarov

christopher said:
I want to convert a value of type T where sizeof(T) <= sizeof(void*) into a
void* and back again.

OK. I suppose it's for passing to some kind of third-party function to
be passed back to your callback function...
> I am currently doing it as follows:

void** ppvoid = reinterpret_cast<void**>(const_cast<T*>(&x));
void* x = *ppvoid;

I would strongly recommend just having an operator void* and a constructor
that constructs from 'void*'.
This works on Visual C++ and GCC 3.4 but I suspect it is not the "correct"
way to do things.

I considered the union approach:

template<typename T>
union cast_union {
void* pvoid;
T x;
}

But this doesn't work because T might have non-trivial constructors.

V
 
M

Mike Wahler

christopher diggins said:
Hello,

I want to convert a value of type T where sizeof(T) <= sizeof(void*) into
a void* and back again. I am currently doing it as follows:

void** ppvoid = reinterpret_cast<void**>(const_cast<T*>(&x));
void* x = *ppvoid;

This works on Visual C++ and GCC 3.4 but I suspect it is not the "correct"
way to do things.

I considered the union approach:

template<typename T>
union cast_union {
void* pvoid;
T x;
}

But this doesn't work because T might have non-trivial constructors.

Any help would be most appreciated.

Well, if type 'T' is not a pointer type, you're outside the
realm of standard C++. The only types you can convert to/from
'void*' without UB or IDB are other pointer types. Check the
documentation for each compiler you use to see if/how it
implements such conversions.

-Mike
 
C

christopher diggins

Victor Bazarov said:
OK. I suppose it's for passing to some kind of third-party function to
be passed back to your callback function...

No. I am doing something much more sinister ;-)
I would strongly recommend just having an operator void* and a constructor
that constructs from 'void*'.

I can't modify T unfortunately.
 
C

christopher diggins

Well, if type 'T' is not a pointer type, you're outside the
realm of standard C++. The only types you can convert to/from
'void*' without UB or IDB are other pointer types. Check the
documentation for each compiler you use to see if/how it
implements such conversions.

Is the following IDB?

template<typename T>
void fubar(T* x) {
void* pvoid;
if (sizeof(x) <= sizeof(pvoid)) {
new(&pvoid) T(x);
}
...
reinterpret_cast<T*>(pvoid)->~T();
}
 
V

Victor Bazarov

christopher said:
Well, if type 'T' is not a pointer type, you're outside the



Is the following IDB?

What is 'IDB'?
template<typename T>
void fubar(T* x) {
void* pvoid;
if (sizeof(x) <= sizeof(pvoid)) {
new(&pvoid) T(x);
}
...
reinterpret_cast<T*>(pvoid)->~T();
}

I don't understand this. I don't think it does what you need. You might
want to look at

reinterpret_cast<T*>(&pvoid)->~T();

because the 'pvoid' is the _value_ of a 'T', not the address in the case
of 'sizeof(T) <= sizeof(void*)'.

V
 
A

Andre Kostur

OK. I suppose it's for passing to some kind of third-party function
to be passed back to your callback function...


I would strongly recommend just having an operator void* and a
constructor that constructs from 'void*'.

Wouldn't that allow for some inadvertant implicit conversions to things
like bool?
 
V

Victor Bazarov

Andre said:
Wouldn't that allow for some inadvertant implicit conversions to things
like bool?

I think the point is moot since he said he couldn't modify the T class,
but why would that necessarily be bad (as you make it sound)?

V
 
P

Pete Becker

Victor said:
I think the point is moot since he said he couldn't modify the T class,
but why would that necessarily be bad (as you make it sound)?

Because in the modern world of overdesign it's much more important to
write code that's hard to use incorrectly than it is to write code
that's simple and does what's needed.
 
V

Victor Bazarov

Pete said:
Because in the modern world of overdesign it's much more important to
write code that's hard to use incorrectly than it is to write code
that's simple and does what's needed.

I hear sarcasm seeping through here... Would declaring an operator bool
and making it private be enough a work-around?

V
 
C

cdiggins

Thanks for pointing that out. I'll try again:

template<typename T>
void fubar(T* x) {
void* pvoid;
if (sizeof(x) <= sizeof(pvoid)) {
new(&pvoid) T(x);
}
else {
throw 0;
}
...
reinterpret_cast<T*>(&pvoid)->~­T();
}

Is there anything non-conformant or implementation specific about this
code?

TIA
 
P

Pete Becker

Pete said:

Oh, you wanted to know what it was? (Don't mind me, I'm in a silly mood
at the moment).

Storage for a void* might not be suitably aligned for objects of type T.
 
C

christopher diggins

Pete Becker said:
Pete Becker wrote:

Oh, you wanted to know what it was? (Don't mind me, I'm in a silly mood at
the moment).

Silly goose ;-)
Storage for a void* might not be suitably aligned for objects of type T.

Okay, I will confess ... I don't fully understand alignment concerns (as if
it isn't blindingly obvious) ... if you don't mind, please tell me more
about what it that T might not be suitably aligned for a void* (given a
guarantee that sizeof(T) <= sizeof(void*)).

TIA
- Christopher
 
P

Pete Becker

Victor said:
Pete said:
[..]
Storage for a void* might not be suitably aligned for objects of type T.

Even if sizeof(T) <= sizeof(void*) ?

Yes, from a language perspective. There are very few constraints on the
alignment requirements of types other than char and its relatives. In
practice bigger things typically don't have less restrictive requirements.
 
P

Pete Becker

christopher said:
Okay, I will confess ... I don't fully understand alignment concerns (as if
it isn't blindingly obvious) ... if you don't mind, please tell me more
about what it that T might not be suitably aligned for a void* (given a
guarantee that sizeof(T) <= sizeof(void*)).

Hypothetical architecture: floats are 4 bytes and must be aligned on 4
byte boundaries. Pointers are 4 bytes and have no alignment constraints.
So a void* object (referring to the pointer, not to the pointee) can
exist just fine at an address like 32k+1, while a float at that address
would be misaligned. It would have to be placed either at 32k or at 32k+4.

When type puns are involved, "misaligned" is often the right answer. <g>
 
C

christopher diggins

Pete Becker said:
Hypothetical architecture: floats are 4 bytes and must be aligned on 4
byte boundaries. Pointers are 4 bytes and have no alignment constraints.
So a void* object (referring to the pointer, not to the pointee) can exist
just fine at an address like 32k+1, while a float at that address would be
misaligned. It would have to be placed either at 32k or at 32k+4.

When type puns are involved, "misaligned" is often the right answer. <g>


:)

So that is nasty smelling kettle of fish. I guess the solution is to somehow
force alignment of the void*? Any suggestions?

I am thinking of:

template<typename T>
void fubar(T* x) {
char[sizeof(T)] pchar;
if (sizeof(x) <= sizeof(pvoid)) {
new(pvoid) T(x);
}
else {
throw 0;
}
...
reinterpret_cast<T*>(pchar)->~­T();
}

Could this be acceptable?

Thanks a lot for your help!
 

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

No members online now.

Forum statistics

Threads
473,919
Messages
2,570,037
Members
46,444
Latest member
MadeleineH

Latest Threads

Top