
On 28/09/10 01:17, David Abrahams wrote:
At Mon, 27 Sep 2010 23:27:36 +0100, John Bytheway wrote:
Presumably the concept modelled by the predicate merely asserts that its return type is convertible to bool (certainly that's all I had in mind), and in principle !__pred(*__first) is undefined behaviour with respect to the concept.
"Undefined behavior" isn't quite the right word; the concept constraint would prevent the template body from compiling.
For that paragraph I was talking in not-enforced-in-the-language concepts world.
Is your point that an archetype based on valid expressions would fail to detect the flaw in the naive implementation of find_if, but that an archetype based on member definitions would catch it?
[Those things you're calling member definitions are actually called pseudo-signatures. They don't (only) define members.]
Thanks, yes, I had encountered that name, and forgotten it...
Well, no. The flaw isn't in the implementation of find_if; it's in the actual concept requirements imposed by the "valid expression" form of the concept definition. Any concept mechanism that doesn't allow you to write a straightforward find_if is broken.
I'm still struggling; I hope I can entice you to explain a little further. 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); } (I think this is simple enough to warrant an auto concept; no one else in this thread has mentioned them, so I don't know your opinions). So, my first question is: will the above find_if compile? If so, does it imply that predicates must return bool, or merely that they must return something convertible to bool? If the latter, then I don't see any difference from the valid expression approach. 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). John