|
Boost : |
Subject: Re: [boost] [contract] concepts: pseudo-signatures vs. usage patterns
From: Dave Abrahams (dave_at_[hidden])
Date: 2012-10-13 16:34:56
on Sat Oct 13 2012, Andrzej Krzemienski <akrzemi1-AT-gmail.com> wrote:
> 2012/10/12 Dave Abrahams <dave_at_[hidden]>
>
>>
>> on Fri Oct 12 2012, Andrew Sutton <asutton.list-AT-gmail.com> wrote:
>>
>> >>> If I remember correctly, we assumed that a conversion requirement on
>> >>> the result of an operation, would actually convert (if necessary).
>> >>
>> >> What does "if necessary" mean? I can think of at least two different
>> >> ways to decide whether a conversion is necessary.
>> >
>> > If the expression returns bool, no conversion is necessary. If it does
>> > not, then a conversion is needed.
>>
>> Sorry, that's still too vague to tell me what you mean. Surely this has
>> nothing to do with "bool-ness," so I have to assume bool shows up in an
>> example you have in mind. Could you show a concrete example with
>> specific requirements?
>>
>
> Pardon me, if I completely misunderstood your concern.
BTW, Doug Gregor is the one who explained all this to me, years ago, so
it's his concern first.
> This is how I
> understand the issue you describe:
>
> We have a concept requirement like this:
>
> concept Operation<typename Op, typename T>
> = requires(Op op, T t)
> {
> //...
> bool = { op(t) }; // "convertible to bool"
> }
I have to admit that I'm not entirely familiar with the new-fangled
syntax being proposed, but I think I can muddle through your use of it
here. Operation<Op,T> says that declval<Op>()(declval<T>()) is
valid and convertible to bool, right?
> We have the following function template
>
> template< typename Op, typename T >
> requires Operation<Op, T>
> bool fun(Op op, T t) {
> return true && op(t);
> }
>
> We have a following concrete type that models Operation:
>
> class FunnyBool{...}; // almost like bool
> class X{...}; // which will become T
> FunnyBool operation(X x) {...}; // which will become Op
> bool operator&& (bool a, FunnyBool b) {}; // which will do some unexpected
> thing
Yes, you're on the right track here...
> When we instantiate:
>
> fun(operation, X{});
>
> which operator&& will be picked? (bool, bool) or (bool, FunnyBool)?
>
> This is the question you ask.
Well, I'm not sure that my entire concern can be captured in this one
example, but this question is certainly an instance of my concern.
> Am I right? If so, the answer I find the most logical would be is
> since the concept is only aware that the type is convertible to bool
> and can only rely on this information, when function fun() is
> instantiated with operation and X, it only sees a restricted version
> of operation and X and indirectly FunnyBool as though 'through concept
> Operation' and must convert FunnyBool to bool before applying operator
> &&.
That's what the pseudo-signature approach does, so you and I agree on
that much. In fact, these are the "loose match" semantics you were
objecting to earlier. :-) Notationally speaking, I think
pseudo-signatures are *much* more suggestive of those semantics than are
valid expressions.
The bigger problem is that the valid expression approach also makes it
possible/easy to specify requirements where the type corresponding to
bool in this example is never explicitly named, e.g.:
bool = { true && op(t) };
value_type = { *it++ };
etc. IIUC these sorts of things cause big problems for typechecking
(exponential explosions?) and usability, but I'd have to defer to others
to describe in detail what those issues are.
> Of course this is achievable only in concepts as language feature. Any
> use-pattern-based concept library will not be able to implement this
> behavior, as far as I am aware.
On the other hand, a pseudo-signature-based library conceivably could.
-- Dave Abrahams BoostPro Computing Software Development Training http://www.boostpro.com Clang/LLVM/EDG Compilers C++ Boost
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk