
Fair enough; it is a natural requirement to start with given the "obvious" implementation using conditionals.
Yeah, but now we're back at implementation-driven requirements.
Right, but all type requirements are implementation-driven. We just shouldn't state them in terms of the implementation.
Then clamp(x, lo, hi) and clamp((U)x, (U)lo, (U)hi) will give the same result (which, I think, is what you want anyway), and the latter is as defined above. Indeed, whatever ordering is decided upon should imply that clamp(x, lo, hi) and clamp((U)x, (U)lo, (U)hi) give the same result, and I think this almost necessitates that (a < b) == ((U)a < (U)b).
I think you can strike "almost" :-)
The equivalence of comparisons makes the algorithm meaningful. That's what I was looking for. If you skip that requirement, then your algorithm could mean anything. The only potential problem is that you should be writing U(a) instead of U(b). I'm not sure that common_type, if one exists guarantees the equivalence of C casts and initialization.
A problem that I see is that (a < b) == ((U)a < (U)b) fails for some common use cases (e.g., char const * and std::string) where the clamp implementation still works and does what you'd expect.
I don't think this fails for C-strings and std::string. Last I checked std::string overloaded < for C-strings and it definitely has a non-explicit constructor taking a C-string.
clamp(x, lo, hi)
and
clamp((U)x, (U)low, (U)hi)
should give the same result.
...right... so now should every algorithm be generalized that way, with the attendant complications in specification? Do we need the same interface for, say, GCD? Why not just ask the caller to cast to the common type first?
Good question. There seems to be a lot of precedence in the std library for multi-type generalization. I'm not suggesting that this is good or bad, only a decision to be considered. Unifying type arguments leads to much simpler requirements at the cost of generality and, as Phil demonstrates, performance. Generalization gets us into these discussions. Choose your poison :)