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 _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost