|
Boost : |
Subject: Re: [boost] [guidelines] why template errors suck
From: John Bytheway (jbytheway+boost_at_[hidden])
Date: 2010-09-28 15:18:37
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk