Parametric subtyping, StackOverflowError issues

I think I don’t do it right, although it works (more or less)… Given a

using StaticArrays

struct Position{T} <: FieldVector{3, T}
    x::T
    y::T
    z::T
end

I can create and calculate nicely with the type:

> Position(1,2,3)
3-element Position{Int64}:
 1
 2
 3

but I get a StackOverflowError when I pass values with differing types:

> Position(1.0,2,3)
StackOverflowError:

Stacktrace:
 [1] Position(::Float64, ::Vararg{Any,N} where N) at /home/tgal/.julia/packages/StaticArrays/VyRz3/src/convert.jl:4
 [2] Position(::Tuple{Float64,Int64,Int64}) at /home/tgal/.julia/packages/StaticArrays/VyRz3/src/FieldVector.jl:20
 ... (the last 2 lines are repeated 9988 more times)
 [19979] Position(::Float64, ::Vararg{Any,N} where N) at /home/tgal/.julia/packages/StaticArrays/VyRz3/src/convert.jl:4

I am not sure how to do it correctly so that the type conversion is made automatically. I also tried to somehow bring in a where T<:Real, but no success with the syntax yet, also I am not sure if it would even help :wink:

struct Position{T} <: FieldVector{3, T}
    x::T
    y::T
    z::T
end

says that x, y, z share the same type (T, whatever that happens to be)
so Position(1.0, 1, 1//1) is not going to work without some intermediation.

Position(x,y,z) = Position(promote(x,y,z)...)

now it works because the types are made uniform

julia> Position(1.0, 1, 1//1)
3-element Position{Float64} with indices SOneTo(3):
 1.0
 1.0
 1.0

For best throughput, you could define an inner constructor that is used when the types of x, y, z are given the same, and the outer constructor as shown above for all other cases (mixed types).

struct Position{T} <: FieldVector{3, T}
    x::T
    y::T
    z::T

    Position(x::T, y::T, z::T) where {T} = new{T}(x, y, z)
end

Position(x, y, z) = Position(promote(x, y, z)...)
3 Likes

Awesome, thanks :slight_smile: