Template constraints in D

Bill Baxter dnewsgroup at billbaxter.com
Sat Jun 21 16:12:50 PDT 2008


Walter Bright wrote:
> Bill Baxter wrote:
>> A more natural way to declare required functions would be nice.
>>
>> First of all, about the isAddable example, can't you just use T.init 
>> instead of writing an anonymous delegate?  Like
>>    __traits(compiles, T.init + T.init)
> 
> I think you're right.
> 
>> Anyway, for a less trivial example I think that becomes pretty 
>> cumbersome.  E.g.:
>>
>> concept Stack<typename X> {
>>   typename value_type;
>>   void push(X&, const value_type&);
>>   void pop(X&);
>>   value_type top(const X&);
>>   bool empty(const X&);
>> };
>>
>> is going to translate to something like this?:
>>
>> template Stack(T)
>> {
>>     const Stack =
>>         is(T.value_type) &&
>>         __traits(compiles, (T t, T.value_type v) { push(t, v); }) &&
>>         __traits(compiles, (T t) { pop(t); }) &&
>>         __traits(compiles, (T t) { top(t); }) &&
>>         is(typeof(top(T.init))==T.value_type) &&
>>         __traits(compiles, (T t) { empty(t) }) &&
>>         is(typeof(empty(T.init))==bool);
>> }
>>
>> I hope you can work out a way to give this a more natural syntax, like 
>> Concepts will have in C++0x.
> 
> You're the first I've heard say that Concepts have a natural syntax! 

Well, I didn't go very far into that spec document you link to, but I 
think the Stack example above (which I took from there) is really 
straightforward.  It looks just like a kind of interface declaration. 
Since concepts are trying to express compile-time interfaces, that makes 
plenty of sense.

> But let me try:
> 
> template Stack(T)
> {
>     const Stack =
>         __traits(compiles,
>         (T t)
>         {    T.value_type v = top(t);
>              push(t, v);
>              pop(t);
>              if (empty(t)){}
>         });
> }
> 
> The idea is that the desired operations are expressed as operations, 
> rather than as function signatures.

I do like the idea -- show the actual code you want to work, not 
something one-step removed like "has an opAdd member".  Still, anything 
containing __traits looks like an afterthought.

Also, I'm not sure how it's going to work in C++, but isn't the compiler 
going to have a hard time reporting errors in that kind of thing? 
Failure to instantiate could be because of a very minor typo in the big 
list of constraints.

I'm not sure how C++ will deal with that, but I think it's another place 
where concept maps help.  They introduce a little redundancy.  They give 
you a place to say "I think type X satisfies concept Y, and here's how". 
  That gives the compiler a place to say, "No you're wrong, type X does 
not satisfy concept Y because Foo isn't actually a method of X".  It 
seems like it should be possible to generate very readable error 
messages from that.


>> An unrelated comment is that I don't think it is relevant or 
>> respectful to compare the lengths of the specs.  The spec for Concepts 
>> that you link to includes many many more in depth examples than the D 
>> spec does.  It's an apples vs oranges comparison.  So 5 pages vs 49 
>> pages really doesn't have much meaning at all.
> 
> I wished to make the point that D constraints build on what one already 
> knows - how to write a D expression. Concepts, on the other hand, have a 
> major new syntax and semantic thing that must be learned. Perhaps I 
> expressed the point badly, do you have a suggestion?

I think the number of new keywords expresses that well enough.  You 
could also add something like "new syntactic constructs:  1  vs [however 
many concepts add]".  I think you can pretty much count up the gray 
boxes in the Concepts spec to get that number.  Or maybe call it "new 
productions added to grammar".

--bb



More information about the Digitalmars-d mailing list