
Generalization gets us into these discussions.
And, since turn-about is fair play... Generalization should be use-case-driven, no?
Well said, sir :)
Yes, but the std library's concept requirements are too loose. If we had had concepts in the language, against which we could check the specification, when the STL was first implemented, that wouldn't have happened. But maybe it would be a good time to ask you to list some examples from std, so we can talk in terms of specifics.
We could talk about find() because its so obvious. template<typename I, typename T> I find(I first, I last, T const& value) { for( ; first != last; ++first) { if(*first == value) return first; } return last; } The == falls under the same topic of discussion as < for clamp. For different, unrelated types, what meaning can you possibly assign to the expression. The same reasons apply. Equality is reflexive, symmetric, and transitive, and should probably define real equality and not just an equivalence relation. Try showing that == on unrelated types satisfies the reflexive property. You could require that T and the value type be the SameType, but that's really strict. You could replace T with iterator_traits<I>::value_type to unify the types; EqualityComparable is meaningfully applied to a single type instead of the incredibly vague and meaning-free HasEqual. This allows conversion, but at a small cost of performance. If generality is needed, you could phrase requirements in terms of common type, like we've done in this discussion. I don't think that any solution is inherently better than any other; except with respect to the use cases that you need it to satisfy. EoP takes the first approach because the language in the book doesn't deal with conversions. I think the second is a reasonable since it allows requirements to be stated clearly and simply. I think the last is fine because it is both general and precise, although the exact requirements might be harder to state. We could have similar discussions for every algorithm where there are two value types involved in an expression. I'd guess that this is 60-70% of all the STL algorithms?