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<[email protected]>: >>>> 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:[email protected]
http://jeberger.free.fr
Jabber: [email protected]
signature.asc
Description: OpenPGP digital signature
