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