See this discussion for further discussion and, in particular, its recommendation of ForwardMethods.jl.
While sometimes I think about forwarding literally all methods, I usually end up deciding that’s too broad a brush. It also tends to break down. For example, if you wrap a <:Number
, you might want sqrt
to unwrap the value, apply sqrt
and re-wrap it. But you don’t want to do this for another function like >=(0)
, since you want that to return a Bool
.
While doing this only for all functions explicitly defined for the wrapped type sounds more sensible, recall that many methods are duck-typed, so that list is very incomplete (for example, it would miss any of the many methods that take arbitrary arguments and promote
them).
If you aren’t using a package’s macro but instead defining forwards manually for an explicit list, metaprogramming can be useful:
# unary functions
for f in [:abs, :abs2, :sqrt, :exp, :log, :sin, :cos, :tan] # and many more
@eval Base.$f(x::MyType) = MyType(Base.$f(x.value))
end
# binary functions
for f in [:+, :-, :*, :/, :^] # and many more
@eval Base.$f(x::MyType, y::Number) = MyType(Base.$f(x.value, y))
@eval Base.$f(x::Number, y::MyType) = MyType(Base.$f(x, y.value))
@eval Base.$f(x::MyType, y::Number) = MyType(Base.$f(x.value, y.value))
end