I think, because of the way the Python bindings for ROOT are created, that __mul__ can only be linked to one of the overloaded operator* functions in TVector2, namely, the first one that is called in the script.
Therefore, both of these scripts fail on Line 3 with could not convert argument 2:
import ROOT
v1 = ROOT.TVector2(1, 1) * ROOT.TVector2(2, 2) # this works
v2 = ROOT.TVector2(1, 1) * 5 # this doesn't
import ROOT
v1 = ROOT.TVector2(1, 1) * 5 # this works
v2 = ROOT.TVector2(1, 1) * ROOT.TVector2(2, 2) # this doesn't
Is there an obvious way to force the TVector2 to use one version of operator* vs. another, or do I have to use TVector3 with a zero for the z component, or implement either the scalar multiplication or dot product manually myself, whichever comes second?
Note: This isn’t a problem for TVector3 because the set of methods are completely different, for some reason: TVector3::Mag() is TVector2::Mod() and TVector3 defines a TVector3::Dot(TVector3), while TVector2 overloads the * for both scalar multiplication and the dot product. The Pythonic way of overloading __mul__ is to “duck type”: assume the passed argument is the right type, try something, then handle the exception:
class TVector2(object)
...
def __mul__(self, second):
try:
return self.X()*second.X() + self.Y()*second.Y()
except:
return TVector2(self.X()*second, self.Y()*second)
(and similar code for __rmul__)
… but I guess this was difficult to do with compiled code or with automated Python bindings.