I want to define a type that holds one vector of Float64
and another of ComplexF64
, but I want their containers are of the same type. For example, I want them to be Vector{Float64}
and Vector{ComplexF64}
, or CUDA.CuVector{Float64}
and CUDA.CuVector{ComlpexF64}
, etc.
Initially I hoped something like this to work:
struct MyWrongType{V<:AbstractVector}
vr::V{Float64}
vc::V{ComplexF64}
MyWrongType{V}(r,c,n) where {V<:AbstractVector} = new(fill(r,n), fill(c,n))
end
but this generates an error (related threads: Cannot define parametric type with parametric field, Type definition):
ERROR: TypeError: in Type{...} expression, expected UnionAll, got a value of type TypeVar
A working approach is something like
struct MyType{VR<:AbstractVector{Float64},VC<:AbstractVector{ComplexF64}}
vr::VR
vc::VC
MyType{VR,VC}(r,c,n) where {VR<:AbstractVector{Float64},VC<:AbstractVector{ComplexF64}} = new(fill(r,n), fill(c,n))
end
but this does not force VR
and VC
to be of the same container type.
The most satisfactory solution I came up with is to use the above working approach and additionally to define an outer constructor that takes the container type V
as a constructor argument (rather than a type parameter):
MyType(V, r, c, n) = MyType{V{Float64},V{ComplexF64}}(r,c,n)
Then I can do things like
using StaticArrays, CUDA
m_vector = MyType(Vector, 0.0, 0.0im, 10)
m_static = MyType(SVector{10}, 0.0, 0.0im, 10)
m_cuda = MyType(CuVector, 0.0, 0.0im, 10)
Each of these instances holds real and complex vectors of the same container type.
I’m considering taking this approach, but wondering if there is a better, more standard approach to solve the described problem.