I have an incredibly exciting library that can translate points: it should work with any point types
template
auto translate_point(T &p, int x
In this case, both of your overloads are under-constrained. You can't really call the second one with StupidPoint
, but that isn't observable at the point of overload resolution. If you constrain both properly, you'll remove the ambiguity in this case:
template
auto translate_point(T &p, int x, int y) -> decltype(p.x += x, p.y += y, void()) { ... };
template
auto translate_point(T &p, int x, int y) -> decltype(p[1] += y, void()) { ... } // prefer checking 1, so you don't allow an operator[] that takes a pointer
Now, if operator[]
returned an int&
instead, this would still be ambiguous. In that case, you'd need a way to order the two overloads (maybe with an extra argument that is either int
or ...
?), or simply disallow that case. That's a separate design decision.