
On Sep 28, 2010, at 12:18 PM, John Bytheway wrote:
For concreteness, I imagine that a "straightforward" implementation of find_if in concept land looks something like this (like everyone else here I reserve the right to get the syntax wrong, in my case having never worked with concepts this way before):
template<InputIterator I, typename F> I find_if(I start, I const finish, F const p) where Predicate<F, InputIterator<I>::value_type> { while (start != finish && !p(*start)) ++start; return start; }
Thus, I imagine that the pseudo-signature technique allows this implementation.
Furthermore, I would have written the Predicate concept like
auto concept Predicate<typename F, typename A> { bool operator()(A); }
Small syntax correction: You need F as the first parameter of that operator ().
So, my first question is: will the above find_if compile?
Yes.
If so, does it imply that predicates must return bool, or merely that they must return something convertible to bool?
The latter. That's why they're called pseudo-signatures.
If the latter, then I don't see any difference from the valid expression approach.
The difference is that, no matter what the actual predicate returns, it is treated as a bool.
So, I guess it is the former? In that case I think I see what you're driving at. It prevents me from writing a perverse predicate such as:
struct funny_bool { operator bool() { return true; } bool operator!() { return true; } };
struct predicate { funny_bool operator()(int) { return funny_bool; } };
although that would have been fine under the valid-expressions framework (and have potentially surprising behaviour).
No, if I remember correctly how concepts work, that's actually a perfectly valid thing to do. In find_if<InputIterator, predicate>, p(*start) is bound to the pseudo-signature operator(), which returns a bool. Therefore, the result of p(*start) is converted to a bool first, and only then is operator ! applied to it, so you get the normal not-operator. But I might remember incorrectly. Sebastian