|
Boost : |
From: C. Green (postmast.root.admi.gov_at_[hidden])
Date: 1999-11-05 11:29:24
At 10:15 AM -0500 1999.11.05, Beman Dawes wrote:
>Darin Adler wrote:
>
[Darin's comments on implicit conversions in implicit_cast]
>But implicit_cast<> needs more than reactivating the warnings. There
>are other issues. (For reference, the current definition is given:)
>
> template< typename Target, typename Source >
> inline Target implicit_cast( Source s ) { return s; }
>
>Issue 1: Valentin Bonnard has pointed out the conversion should be
>done at the argument, in case it requires an access privilege which
>implicit_cast doesn't enjoy. I guess this would be formulated as:
>
> template< typename T >
> inline T implicit_cast( T s ) { return s; }
>
>Issue 2: Ivan Johnson has pointed out a implicit_cast slicing
>problem:
>
[snip]
> Derived d;
> Derived& rd = d;
> Base& rb = implicit_cast<Base&>(rd);
I assume this must be for the first (two-typename template func), because
the second one (single typename) will work fine here too.
> if ( &rd != &rb )
> cout << "oops\n";
[snip]
>Issue 3: Issue 1 and 2 interact. The proposed resolution for 2
>[take Source& instead of plain Source] doesn't fix 1. The proposed
>solution for 1 also fixes 2 for the example given, but silently
>slices if the template parameter is omitted:
>
> Base& rb = implicit_cast(rd); // slices
First, let's assume you show conforming code that compiles:
Base const& rb = implicit_cast(rd);
In other words, this bug is not caught. implicit_cast without a
specification of the destination type is meaningless.
>Anyone have a resolution that solves all three issues?
template<typename T>
struct mirror_type {
typedef T type;
};
template<typename T>
inline T implicit_cast( typename mirror_type<T>::type t ) {
return t;
}
Will this work?
From my reading (and common sense - the compiler can't read the minds of
all classes), type T cannot be deduced for implicit_cast, therefore it must
be explicitly specified.
Side comment, implicit_cast seems to break code that casts to a const ref type:
int const& ir = 1.0; // OK - temp int lives as long as ir lives
int j = ir; // OK
int const& ir2 = implicit_cast<int const&> (1.0); // temp destroyed at
EOS, right?
int j2 = ir2; // undefined
This can be safe if no temp is generated, but how do we know that one is
not being generated? (user-defined conversions, built-in conversion like
above)
We could specialize mirror_type to not have any members for a const ref
type, so the above would be an error (renaming mirror_type to something
more appropriate, of course). template<typename T>
template<typename T>
struct implicit_cast_helper {
typedef T type;
};
template<typename T>
struct implicit_cast_helper<T const&> {
// no members - cause compilation error
};
It is fine for non-const ref types because it cannot be bound to a temporary:
int& ir = 1.0; // illegal, of course
int& ir2 = implicit_cast<int&> (1.0); // illegal for same reason
Unfortunately, this breaks it for users who wish to convert to a base const
ref via a derived const ref.
Better safe than sorry?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk