On 01/26/2011 07:26 PM, Steven Schveighoffer wrote:
On Wed, 26 Jan 2011 12:30:17 -0500, spir <denis.s...@gmail.com> wrote:

On 01/26/2011 06:27 PM, spir wrote:
Hello,

This fails:

class T0 {}
class T1 : T0 {}
class T2 : T0 {}

unittest {
auto t1 = new T1();
auto t2 = new T2();
T0[] ts = [t1, t2];
}

Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
__trials__.T2
Error: cannot implicitly convert expression ([(__error),t2]) of type T2[] to
T0[]

I guess it should be accepted due to explicite typing 'T0[]'. What do you
think? D first determines the type of the last element (always the last one),
here T2. Then, /ignoring/ the array's defined type, tries to cast other
elements to the same type T2. It should instead, I guess, check all elements
are compatible with the defined array type.
An additional enigma is why the failing element t1 is said to be of supertype
T0 --which is also correct-- while it retained t2's exact type T2. ???

Anyway, is there a workaround?

PS: this works, but I would prefere a solution with all casting:
T0[] ts = [cast(T0)t1, cast(T0)t2];
I consider this issue a bug, at least when the array is explicitely typed.
What do you think?

It's not a bug, the type of an expression does not depend on the type it's
assigned to. Essentially [t1, t2] is evaluated *before* looking at what it's
assigned to.

And the array literal code now uses the most 'compatible' type to determine the
type of the array (used to be hard-typed to type of first element). Obviously
it doesn't work correctly here, but I'm not sure it could really work
correctly. I think maybe if one of those elements had type T0, it might
actually compile.

The said element should be, I guess, the last one (seems D start evaluating elements from the right?).
EDIT: this works:
    auto t0 = new T0();
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] ts = [t0, t1, t2];
Seems D check compatibility between actual element types. In the original case of [t1, t2], it does not "see" that T1 & T2 have a common supertype. I would like to know why the original error message assigns speaks of type T0 (for t1, obviously).

What about a workaround? Hum... This works:

void feed (T) (ref T[] array, T[] elements...) {
    foreach (element ; elements)
        array ~= element;
}
unittest {
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] array;
    array.feed(t1, t2);
    writeln(array);
}

The trick indeed is using '...'. May feed be useful in std.array? (With a variant for AAs?) (Called it feed instead of init because it can also extend a non-empty array, with a set of new elements one could not write literally, neither.)

Denis
--
_________________
vita es estrany
spir.wikidot.com

Reply via email to