Boost logo

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