I have exactly the same requirement.
Additionally, I often have more than 2 fields and also change the fields of
my custom types.
So I use a slightly more general version of the above:
function CompositeBinaryOp(T::Symbol, op::Symbol)
expressions = [ :($op(x1.$field, x2.$field)) for field in
fieldnames(eval(T)) ]
body = Expr(:call, T, expressions...)
quote
function $op(x1::$T, x2::$T)
return $body
end
end
end
type M
a
b
end
import Base: +, -, *, /, ^
for T in [:M]
for op in [:+, :-, :*, :/, :^]
#eval(CompositeBinaryOp(T, op))
code = CompositeBinaryOp(T, op)
println(code, "\n")
eval(code)
end
end
The advantage here for me is that I can change the fields (number, type
order etc.) and operators don't need manual updating.
I have similar functions for copy constructors, unary operators etc.