Suppose I have several parametric wrapper types, like so (toy example):
abstract type AbsWrapper end
struct WrapperA{T <: Real} <: AbsWrapper
x::T
end
struct WrapperB{T <: Real} <: AbsWrapper
x::T
end
I’d like to write converter functions that convert instances of an AbsWrapper
to a “similarly typed” value wrapping a Float64
. E.g.
to_float64_form(w::WrapperA) = WrapperA(Float64(w.x))
Great, this works! And if I have just two wrapper types and one conversion, two one-line functions are all I need. But suppose I have types WrapperA
, WrapperB
, WrapperC
, etc., and I want to write converters to_float64_form
, to_float32_form
, to_rational_form
,… Then there are (number of types) * (number of conversion) functions to write, and the source code gets repetitive. This can be solved (or at least mitigated?) with @eval
, e.g.
for T in [WrapperA, WrapperB]
@eval to_float64_form(val::$T) = $T(Float64(val.x))
end
But I’m not sure if @eval
is necessary here. This feels like a use case that should be solvable with a single parametric method, but I’m struggling. Is @eval
the preferred way to handle this, and if not what is best practice?