Search code examples
pointersvalageneric-interface

Nullable pointer as return value in Vala


Imagine we have something like this (it's just an example)

public interface Foo : GLib.Object {
    public abstract double *f();
}

public class Toto : GLib.Object, Foo {

    private double i;

    public Toto(double i = 0) {
        this.i = i;
    }

    public double *f() {
        return &i;
    }

    public static int main(string[] args) {
        Foo a = new Toto(42.0);
        double i = *a.f();
        stdout.printf("%.3f\n", i);
        return 0;
    }
}

this code works perfectly fine, but the problem is that Foo must be generic with public abstract T *f(), so Toto must implement Foo<double>, but

`double' is not a supported generic type argument

(and my first question is "why?", as far as i know i can use int for example without any problem)

so it's Foo<double?> and i need something like double i = (!) *(a.f()), but it's just doesn't work (at the C level)

error: invalid use of void expression i = (gdouble) (*(*_tmp1_));

so how can i use f() method?

(my vala version is 0.36.3)


Solution

  • Why do you use pointers in Vala in the first place? (That is discouraged, pointers are in the language for corner cases.)

    A nullable type in Vala is a pointer in the generated C code.

    So one way to tackle this is:

    public interface Foo<T> : GLib.Object {
        public abstract T f();
    }
    
    public class Toto : GLib.Object, Foo<double?> {
    
        private double i;
    
        public Toto(double i = 0) {
            this.i = i;
        }
    
        public double? f() {
            return i;
        }
    
        public static int main(string[] args) {
            Foo<double?> a = new Toto(42.0);
            double? i = a.f();
            stdout.printf("%.3f\n", (!) i);
            return 0;
        }
    }
    

    This compiles and works perfectly fine with valac 0.36.3 here.

    The type signature of the generated C function for Toto.f is:

    static gdouble* toto_real_f (Foo* base);