|
Boost : |
Subject: Re: [boost] [guidelines] why template errors suck
From: Doug Gregor (doug.gregor_at_[hidden])
Date: 2010-09-28 19:01:02
On Tue, Sep 28, 2010 at 10:45 AM, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
> On 28/09/10 18:33, David Abrahams wrote:
>>
>> At Tue, 28 Sep 2010 10:00:54 -0500,
>> Andrew Sutton wrote:
>>>
>>> It seems to me that writing constraints in terms of valid
>>> expressions gives you flexibility when you want it, but doesn't
>>> preclude the strengthening of requirements when needed.
>>
>> It's not that there's anything you *can't* express with valid
>> expressions, it's that they're difficult to use correctly, and the
>> most natural way of using them creates a big mess for algorithm
>> writers. Furthermore, they don't offer any compelling value over the
>> alternative.
>
> Please demonstrate how you check that a type models a concept without using
> a set of valid expressions to define the concept, but only with signatures
> in an archetype-like fashion.
See 14.9.2.1 [concept.map.fct]p4 in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2773.pdf
> My insight is that you can't.
There are several ways to accomplish this. The concepts proposal cited
above mapped signatures to valid expressions when checking a type
against a concept, but one could also perform a signature match with
varying degrees of "fuzziness" (for references, convertibility, etc.).
> Therefore what compelling value expressions give over archetypes becomes
> fairly obvious: they do what we want, while archetypes don't and do
> something different.
Having spent several years engrossed in concepts, I can tell you
outright that valid expressions rarely "do what we want" from the
type-checking perspective. There's a simple example from earlier in
this thread:
>>>bool(f != l)
>>>bool(p(*f))
>>Isn't bool(x) equivalent to (bool)x? I think that's valid code for
>>any x.
>That's valid code for any object x of a built-in type or that is implicitly convertible to any built-in type.
Since the valid expression has the conversion written explicitly, as a
function-style cast, a class type with an explicit conversion to bool
(or any built-in type) would also meet the requirements of this valid
expression. The obvious point here is that the simplest valid
expression we've seen in this discussion has already been
misinterpreted. But, that's not the interesting part.
Say we have values "f" and "l" in a constrained template with the
valid expression "bool(f != l)". What can we write in the constrained
template, such that we're sure it will instantiate correctly?
bool(f != l)
Yep, that works. It's just like the valid expression shows.
(bool)(f != l)
Yep, that works, since function-style and C-style casts have the same behavior.
if (f != l)
Yes, that works, because this is contextual conversion to bool, so
explicit conversion operators will be considered.
bool result = f != l;
Nope, doesn't work, because we only said that we require an explicit
cast to "bool" to work. The constrained template must be considered
ill-formed, or you've lost type soundness.
if (!(f != l))
Nope, doesn't work, because we only said that f != l must be
explicitly convertible to bool; we didn't say that it needed to have a
valid ! operator.
some_function_template(f != l); // where template<typename T> void
some_function_template(T);
what does 'T' deduce to in this case? How would we describe the other
requirements on the result type of f != l, so that we could ensure
that the we meet some_function_template's constraints on 'T'?
> You said it yourself: expressions are only half the solution; archetypes are
> the other half. They're not the whole and they're no substitute for using
> expressions to define and test concepts.
The whole point of concepts is that they have to be both. One
description allows you to type-check a template definition and check a
type against the requirements of a concept, and when both pass, you
want to guarantee that the template instantiates property. That's
type-soundness, and it is a fundamental goal of concepts.
Valid expressions are fine for checking whether a type conforms to a
concept, but they're poor at describing requirements for type-checking
templates. Signatures naturally support type-checking in templates,
and also make it fairly easy to check whether a type conforms to a
concept.
- Doug
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk