Boost logo

Boost :

From: Philippe A. Bouchard (philippeb_at_[hidden])
Date: 2003-02-28 09:38:11


Fernando Cacciola wrote:

[...]

>> BTW implicit cast to reference types are not implicit under GCC,
>> they have to be called explicitly.
>
> Yes, this is the conformant behaviour AFAIK

But it will work if the cast operator is not a member template. Maybe
"template cast to reference type" should be added in the standards.

>> Template casts do not seem to be defined in the
>> standard...:
>>
>> template <typename T>
>> struct optional
>> {
>> template <typename U>
>> operator optional<U> const & () const
>> {
>> return * reinterpret_cast<optional<U> const
> *>(static_cast<U
>> const *>(reinterpret_cast<T const *>(storage_)));
>> }
>>
>> ...
>> };
>>
> This is seriously wrong:
>
> (a) reinrepret_cast<> has implementation-defined behaviour,
> which means that is totally useless in portable code.
>
> (b) you don't need reinterpret_cast<> to obtain a 'T const*'
> from the aligned_storage whithin the optional: look at the optional
> code.
>
> (c) EXTREMELY WRONG: you're converting a pointer to aligned_storage<>
> into a pointer to optional<>, !!! but aligned_storage is a
> _data_member_
> of optional!!!

I know it's wrong, it was just a dummy example; my main idea behind this was
simply to cast the object to one of its parent. static_cast<> was there
just to generate a compiler error if you tried to up / down cast to an
object not in the same hierarchy (ex. optional<C>).

>> inline void foo(optional<A> const &)
>> {
>> }
>>
>> int main()
>> {
>> optional<B> b;
>>
>> //foo(b);
>> foo(b.template operator optional<A> const & <A> ());
>> }
>>
>>
>> Also, the advantage of casts to reference types is that they do not
>> create any temporary objects implicitly.
>>
> But does not create a new objet either!
> A conversion is REQUIRED to give a NEW OBJECT,
> otherwise there's no conversion at all: since the object remains
> exactly
> the same, you just BROKE the type system by binding a reference of a
> completely unrelated type to the same object.
> The only case when you can do something _similar_, that is, when
> you can't do a _convertion_ but you can do a _cast_, is when the
> reference type (or pointer type, for that matter) is of the type of a
> non-ambiguous accesible base-class subobject
> (because the object dynamic type is covariant with the
> reference/pointer static-type).

I do not wish to create a new object. Since there is absolutely no way to
control pointer behaviours, I aim reference types.

Again the m_initialized boolean is problematic if you do not add a second
virtual table, because the address of the pointer to the object may be
shifted. (void *) (A *) m_storage could be different from (void *) (B *)
m_storage in other words, but (void *) & optional<A>() must be the same as
(void *) & optional<B>() and I do not think this is what Dave really wanted.

>> I do not see in what it can be dangerous.
>>
> I do :-)
> And I see the danger in reinterpret_cast<>; stay away from it.

:(

>> What do you think?
>>
> Please, read my original response to David Held and look carefully at
> the optional implementation.
> As I said, you could only get half away with such a _conversion_ if
> you purposedly _slice_ the U subobject out of a T object
> (if U is in fact a subobject of T), and wrap it into a NEW optional.
> But you can't go back to a T, so this is not polymorphism, is
> straight up conversion, just like converting a long double to a short
> loosing
> along the way all the bits that don't fit.

I agree, but if m_storage was the first object of the class optional<>,
other rules could help the situation a lot.

Like I said, casts to reference type is the only way to simulate pointers to
object because they do not create any new temporary objects and you could do
even more if m_initialized was in a different table. I could write more in
depth another example...

Philippe A. Bouchard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk