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