[Vala] Boxed type generics

86 views
Skip to first unread message

Stephan Hilb

unread,
Mar 19, 2012, 8:59:33 AM3/19/12
to vala...@gnome.org
Hello,

I'd like to do something like the following (somewhat oversimplified):

public T increment<T> (T number) {
return (double?) number + 1;
}
public static void main () {
stdout.printf("%f\n", increment<double?> (4.7));
}

Unfortunately the C-compiler complains about not being able to convert
the double to a pointer type in the return statement.
I have found out this works as expected:

public T increment<T> (T number) {
double tmp = (double?) number;
tmp += 1;
return &tmp;
}

This, however, seems not to be the right thing to do. Could someone
explain how to handle those boxed types correctly without resorting to
the address-of-operator?

Thanks,

Stephan

_______________________________________________
vala-list mailing list
vala...@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list

Tal Hadad

unread,
Mar 20, 2012, 8:05:40 AM3/20/12
to Vala Mail List

Even known it's doesn't sound like that, and it's work in .Net, double? is always
a pointer type. It's the same as double*. This explains the first example error.
In the second one, you convert some type to double* and then to double(in the
deceleration "double tmp"). The compiler seems to ignore the first conversion,
and skip to the second.

In conclusion, use (double) instead of (double?). If you want to achieve a null
passing in by value(i.e. not pointer), pass another Boolean which tells if it's
empty.

Yours,
Tal

> Date: Mon, 19 Mar 2012 13:59:33 +0100
> From: ste...@ecshi.net
> To: vala...@gnome.org
> Subject: [Vala] Boxed type generics

Stephan Hilb

unread,
Mar 20, 2012, 5:32:41 PM3/20/12
to vala...@gnome.org
> In conclusion, use (double) instead of (double?).

I'd happily use (double), as it makes sense. But the generated c-code
is wrong and the C-compiler complains:

error: pointer value used where a floating point value was expected

That is quite understandable when looking at the generated c-code,
which tries to cast the incoming pointer generic type directly to
gdouble.


Another example:

public class Test<T> {
public T number;
public void set_number (T number) {
double tmp = (double) number;
this.number = tmp;
}
}

One would assume, that the first line in set_number method is correct
(if the object constructed by "new Test<double>()"). Vala doesn't
complain, but the c-compiler does. The generated C code in this case:

void test_set_number_generic (Test* self, gconstpointer x) {
gconstpointer _tmp0_;
gdouble tmp;
gpointer _tmp1_;
g_return_if_fail (self != NULL);
_tmp0_ = x;
tmp = (gdouble) _tmp0_;
_tmp1_ = ((tmp != NULL) && (self->priv->t_dup_func != NULL)) ?
self->priv->t_dup_func ((gpointer) tmp) : ((gpointer) tmp);
((self->number == NULL) || (self->priv->t_destroy_func ==
NULL)) ? NULL : (self->number = (self->priv->t_destroy_func
(self->number), NULL));
self->number = _tmp1_;
}

Again a pointer _tmp0_ is being casted to gdouble, which is wrong.
When using (double?) instead of (double), the c-code in this line is
like this:

tmp = *((gdouble*) _tmp0_);

This is correct, since _tmp0_ in this case is a pointer to a boolean and
tmp should hold it's value. So quite oddly casting to (double?) seems to
work.

However, the real problem is when trying to assign the value to the
class member:

error: invalid operands to binary != (have ‘gdouble’ and ‘void *’)
error: cannot convert to a pointer type
error: cannot convert to a pointer type

the corresponding line from the c-code above:

_tmp1_ = ((tmp != NULL) && (self->priv->t_dup_func != NULL)) ?
self->priv->t_dup_func ((gpointer) tmp) : ((gpointer) tmp);

So what I need is a way to tell the vala compiler to convert the double
type to the generic type (effectively creating a pointer gdouble*),
which then can be assigned to the classmember (I did this in the
previous email by using the address-of operator, but there has to be a
more vala-way of doing it).

Note: when assigning the classmember from outside the class, everything
is fine:

var test = new Test<double>();
test.number = 1.47;

But how can I do this from inside the class?


Regards,

Reply all
Reply to author
Forward
0 new messages