array of elements of various sybtypes

spir denis.spir at gmail.com
Wed Jan 26 15:31:11 PST 2011


On 01/26/2011 07:26 PM, Steven Schveighoffer wrote:
> On Wed, 26 Jan 2011 12:30:17 -0500, spir <denis.spir at 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



More information about the Digitalmars-d-learn mailing list