Concrete typing for Type{T} struct fields

Dear all,

I would like to create a struct that holds a subtype of Real, which I want to use later on to create buffer arrays. I managed to do that in the MWE below, but it seems like the corresponding struct is not a concrete type. Is there anything I can do to alleviate that?

struct TypeHolder{T<:Real}
	type 	::	Type{T}
	function TypeHolder(type::Type{T}) where {T<:Real}
		return new{T}(type)
	end
end
holder = TypeHolder(Float16) #TypeHolder{Float16}
isconcretetype(holder) #false

I get an error with your code because your inner constructor is called TypeHolder2 instead of TypeHolder. If I rename it, then I get what you want if you pass the type of holder to isconcretetype:

julia> isconcretetype(typeof(holder))   # true
1 Like

First, you should use isconcretetype on types such as TypeHolder{Float16}, not values (such as holder in your example):

isconcretetype(typeof(holder))  # true

but then this does not give you much information: by definition of what a concrete type is, the type of holder will always be concrete (since there exists a value, holder, having this type).


I’m actually not sure of what exactly you’re trying to achieve here, but there’s probably no need to store the type as a field in the struct: having it as a type parameter makes it possible to retrieve it when you need it. A minimal example could look like:

struct TypeHolder{T<:Real}
    function TypeHolder(::Type{T}) where {T<:Real}
	return new{T}()
    end
end
holder = TypeHolder(Float16)   # TypeHolder{Float16}
isconcretetype(typeof(holder)) # true (by definition)

# a function that needs to know about T in order to build a buffer
function compute(x::TypeHolder{T}) where {T}
    buffer = Vector{T}(undef, 10)
    do_something_with(buffer)
end
4 Likes

Thank you for the answer and explanation, seems like it should be optimized already then.

Thank you!