C#'s greatest mistakes

"Jérôme M. Berger" jeberger at free.fr
Sun Nov 28 00:17:30 PST 2010


Jonathan M Davis wrote:
> On Saturday 27 November 2010 14:59:09 BLS wrote:
>> On 27/11/2010 16:59, Torarin wrote:
>>> 2010/11/27 Andrei Alexandrescu<SeeWebsiteForEmail at erdani.org>:
>>>> We use template constraints for that kind of stuff.
>>>>
>>>> Andrei
>>> Yes, and that's great, but is there a way to check whether a template
>>> argument matches a defined interface?
>> I could not resist..
>> We should have Implements!
>>
>> Luca has done some work on it.. but it does not compile anymore. However
>> I think the intension is clear.
>> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&a
>> rticle_id=101673
> 
> If you're checking whether it implements an interface, then : should work just 
> like it does with classes. If you're checking whether it has the same functions 
> that an interface requires, then you're not really using interfaces correctly. 
> structs don't implement interfaces. Classes do that. So, either make it a class, 
> or don't use interfaces. If you want to verify that a struct has particular 
> functions needed for the template function in question, then just check whether 
> calling them compiles ( e.g. __traits(compiles, foo.bar()) ). If you have a set 
> of functions that are expected to be there (for instance, to verify that the 
> given type is a certain type of range), then just create template which checks 
> for each of the functions that are supposed to be there and use the template ( 
> e.g. isForwardRange!T ). Interfaces and structs don't have anything to do with 
> each other.
> 
	Note that __traits(compiles, foo.bar()) does not check the return
type. If you want to check the return and parameter types, you wind
up with a very complex and ugly expression. This is very error
prone. Look at the two examples below:

Using __traits(compiles...):
==============================8<------------------------------
template isFooBar(T)
{
   enum bool isFooBar =
      __traits (compiles,
      {
         T t;
         int arg;
         int r = t.foo (arg);
      })
      &&
      __traits (compiles,
      {
         T t;
         float arg;
         bool r = t.bar (arg);
      });
}

template Test(T) if (isFooBar!T) ...
------------------------------>8==============================

Using a fictive "concept" keyword instead of "interface" to avoid
confusions with true interfaces:
==============================8<------------------------------
concept FooBar
{
   int  foo (int);
   bool bar (float);
}

template Test(T) if (is!FooBar (T)) ...
------------------------------>8==============================

	The second one is clearly much easier to write and (especially)
easier to read, which means:
 - It is faster to write;
 - It will contain a lot fewer errors and bugs (especially once you
get into more complex concepts);
 - It is immediately self-documenting.

	Now, it might be possible to do this purely as a library with the
current language if we are willing to re-use the "interface" keyword
to define the concepts.

		Jerome
-- 
mailto:jeberger at free.fr
http://jeberger.free.fr
Jabber: jeberger at jabber.fr

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20101128/36b925bb/attachment.pgp>


More information about the Digitalmars-d mailing list