Search code examples
crystal-lang

Issue inferring type for generic


I have a c library that I bind to, which has many structs that hold data of different types.

@[Link("foo")]
lib LibFoo

  struct IntStruct
    data : LibC::Int
  end

  struct DoubleStruct
    data : LibC::Double
  end

  fun get_int_struct(n : LibC::SizeT) : IntStruct*
  fun get_double_struct(n : LibC::SizeT) : DoubleStruct*

end

I have a generic class where I want the type T to be the type of one of those structs, based off of an input array.

class GenericClass(T)
    @ptr : Pointer(T)
    @obj : T

    def initialize(arr : Array)
        @ptr = infer_type(arr)
        @obj = @ptr.value
    end
end

Where infer_type looks like:

def infer_type(data : Array(Int32))
    return LibFoo.get_int_struct(data.size)
end

def infer_type(data : Array(Float64))
    return LibFoo.get_double_struct(data.size)
end

The code works fine when I explicitly set the type...

GenericClass(LibFoo::IntStruct).new [1, 2, 3, 4, 5]

...but I would like to infer the type.


Solution

  • Maybe providing a custom generalized new method works for you?

    struct A    
    end
    
    struct B    
    end
    
    class Generic(T)
      def self.new(items : Array(A)) forall A
        new(fetch_struct(items))
      end
    
      private def initialize(@struct : T)    
      end
    
      private def self.fetch_struct(items : Array(Int32))    
        A.new
      end
    
      private def self.fetch_struct(items : Array(Float64))
        B.new
      end
    end
    
    p Generic.new([1])
    p Generic.new([1.0])
    

    https://carc.in/#/r/7s6d