Boost logo

Boost :

From: Anthony Williams (anthony.williamsNOSPAM_at_[hidden])
Date: 2002-12-09 03:59:30

Gabriel Dos Reis writes:
> Hi,
> Anthony Williams <anthony.williamsNOSPAM_at_[hidden]> writes:
> [...]
> | > You made youself clear.
> | >
> | > However, there are two running issues originating from a claim of Dave
> | > that dangerous_cast<> might be better than reinterpret_cast<> in
> | > casting from U* to T* (dangerous_cast<> uses the intermediate step
> | > void* via static_cast<>).
> | >
> | > 1) is dangerous_cast<> better than reinterpret_cast<>?
> | >
> | > 2) is it well-defined to dereference the value obtained from
> | >
> | > U* -> void* -> T*
> | >
> | > ?
> | >
> | > You've showed that si U == char, (the case in Dave's example) then it
> | > is well-formed. The other cases are left undefined.
> | >
> | > So the key question (1) is still unanswered.
> |
> | Well, given that we have a valid use when U==(unsigned) char, I think it is
> | certainly better than reinterpret_cast<> in that case.
> I returned back and checked the standard paragraph from which you
> quoted decivise texts; you said:
> Also, 3.9.2p4 says:
> "Objects of cvqualified (3.9.3) or cvunqualified type void* (pointer to
> void), can be used to point to objects of unknown type. A void* shall be
> able to hold any object pointer. A cvqualified or cvunqualified (3.9.3)
> void* shall have the same representation and alignment requirements as a
> cvqualified or cvunqualified char*."
> So casting a void* to/from a char* is a no-op.
> I tend to find that quite conviincing (and agree with you), except
> that it doesn't say that both pointer have the same *value*
> representation as it explicitly says in a paragraph just before:
> 3.9.2/3
> [...] Pointers to cv-qualified and cv-unqualified versions (3.9.3)
> of layout-compatible types shall have the same value representation
> and align-ment requirements (3.9).
> I'm not sure whether
> 1) the difference in wordings is intended;
> 2) really matters in the specific case we're discussing.

Well, it says "representation", which I take to mean both value representation
_and_ object representation --- two types could have the same object
representation, but one provide trap values, and the other not, so the value
representations are distinct, or they could have the same value
representation, but one arbitrarily require an additional byte in its object

Anyway, in this case, I don't think the difference matters.
> Now, let me attempt to address this key question I repeatedly asked
> Can reinterpret_cast<void*>(&foo) give a different from
> static_cast<void*>(&foo)?
> I think the answer is simple: No. The reason is that
> 5.2.10/1:
> The result of the expression reinterpret_cast<T>(v) is the result of
> converting the expression v to type T. [...]
> and converting a Foo* to void* is well-defined.
> Next, reinterpret_cast<char*>(&foo) is well-defined as char* and void*
> are intended to have the same "memory-alias" properties.

I am not sure I agree that this is valid, since this paragraph goes on to say

"Conversions that can be performed explicitly using reinterpret_cast are
listed below. No other conversion can be performed explicitly using

If this does not apply in this case, you could argue that type conversions
allowed by conversion operators and converting constructors could also be done
using reinterpret_cast, which I am sure you'll agree is not valid usage ---
whether or not a conversion has defined semantics when done explicitly using
another *_cast<>, or when done implicitly, does not affect the semantics of
reinterpret_cast<>. I think that conversions to void* are analogous to
derived* to base* conversions --- using static_cast, the compiler will
correctly adjust the pointer if necessary; using reinterpret_cast, it will
not (necessarily --- of course, it is implementation defined).


Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.

Boost list run by bdawes at, gregod at, cpdaniel at, john at