Vala: Passing a generic array corrupts values

血红的双手。 提交于 2019-12-12 19:05:26

问题


How can I pass an array to a generic function? The following code does compile, but the output gets somewhat corrupted:

void foo<T> (T[] arr) {
    foreach (T element in arr) {
        var element2 = (int) element;
        stdout.printf (element2.to_string() + "\n");
    }
}


void main () {
    int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo<int> (array);
}

Output:
0
2
4
6
8
113
0
-1521013800
0
0

What am I doing wrong?


回答1:


You discovered a compiler bug.

The array is treated as an array of pointers and then things go wrong when foreach tries to iterate over that pointer array.

BTW: It works if you compile for 32-Bit, because sizeof(gint) == sizeof(gpointer) there.

The compiler should not allow a value typed array to be passed to the generic function.

This can be fixed by using Gee.Collection<G> instead of an array:

void foo<T> (Gee.Collection<T> coll) {
    foreach (T element in coll) {
        var element2 = (int) element;
        stdout.printf (element2.to_string() + "\n");
    }
}


void main () {
    int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo<int> (new Gee.ArrayList<int>.wrap (array));
}

This works because Gee.Collection<G> has it's own iterator implementation which seems to be safer in this case. It's not a perfect solution either, some Gee types have problems with value type parameters, because they expect the type to be nullable.

Generics in Vala are always a bit tricky, you should not be passing value types into generics.

If you use an int? (nullable int, which is a reference type) it works as expected:

void foo<T> (T[] coll) {
    foreach (T element in coll) {
        var element2 = (int?) element;
        stdout.printf (element2.to_string() + "\n");
    }
}

void main () {
    int?[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo (array);
}

Nullable types aren't perfect either, because they need more memory and they don't perform as good as value types, but that's just the way it is.

The code is still a bit problematic, because you are casting the element to an int (or int? in my version), but I think you know that it's not a good idea, since this is only some test code, right?



来源:https://stackoverflow.com/questions/39449884/vala-passing-a-generic-array-corrupts-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!