Struct with field types defined by parametric type

Say I have a struct MyStruct such that

struct A
...
end

struct B
...
end

struct MyStruct{T <: Union{A, B}}
  t::T
  v::Vector
end

I want v to be of type Vector{Float64} if T == A, else if T == B then v should be of type Vector{ComplexF64}. How can I do that?

yes. e.g.

struct MyStruct{S, T <: Union{A, B}}
  t::T
  v::Vector{S}
  MyStruct(t) = new(t, t isa A ? [1.0] : [1.0+0im])
end

I know I could do this already. However based on this section of the manual , I am concerned about performance with such a solution

Code warntype reports no type instabilities and performance overhead seems minimal:

using BenchmarkTools

module MyModule 

struct A; end
struct B; end

struct MyStruct{S, T <: Union{A, B}}
    t::T
    v::Vector{S}
end

MyStruct(t) = MyStruct(t, t isa A ? [1.0] : [1.0+0im])

struct MyComparisonStruct{T <: Union{A, B}}
    t::T
    v::Vector{Float64}
end

MyComparisonStruct(t) = MyComparisonStruct(t,[1.0])


end # module 

@btime MyModule.MyStruct(MyModule.A()) # 21.052 ns (1 allocation: 64 bytes)
@btime MyModule.MyComparisonStruct(MyModule.A()) # 21.104 ns (1 allocation: 64 bytes)

I had to move out the inner constructor though, it produced some weird error.

In that case, we need to update that section of the manual because this type of pattern is the solution to that problem (so it’s bad if that is unclear).

I’d rewritten that in a way that emphasizes the compile-time resolution

struct MyStruct{T <: Union{A, B}, S}
    t::T
    v::Vector{S}

    MyStruct{A, Float64}(t, v) = new{A, Float64}(t, v)
    MyStruct{B, ComplexF64}(t, v) = new{B, ComplexF64}(t, v)

    MyStruct(t::A, v) = new{A, Float64}(t, v)
    MyStruct(t::B, v) = new{B, ComplexF64}(t, v)
end