isIterable(T)
dsimcha
dsimcha at yahoo.com
Sun Apr 26 11:05:58 PDT 2009
== Quote from Denis Koroskin (2korden at gmail.com)'s article
> On Sun, 26 Apr 2009 21:44:31 +0400, dsimcha <dsimcha at yahoo.com> wrote:
> > I've been thinking a little more about ranges, etc. and it would be nice
> > to
> > have a template for isIterable(T) that simply tells whether an object
> > can be
> > iterated over with foreach, without caring how this iteration works
> > (ranges,
> > opApply, builtin array/AA). I have some use cases where I'm writing very
> > generic functionality and all I need is the lowest common denominator
> > that,
> > given an object T, the following will compile, and to know what type elem
> > would be:
> >
> > foreach(elem; T.init) {}
> >
> > This functionality does not require any of the more advanced features of
> > ranges, just iteration. Is there any good way to write a template for
> > this?
> > Since foreach is a statement, is(typeof()) and __traits(compiles) are
> > out.
> // Not tested
> template isIterable(T)
> {
> static if (is(typeof({foreach(elem; T.init) {}})) {
> const bool isIterable = true;
> } else {
> const bool isIterable = false;
> }
> }
Wow, IDK why I thought that wouldn't work. I must have made some minor
syntactical error b/c I tried the same thing a few minutes ago, yet somehow yours
works. Only thing is, you forgot a ) at the end. Also, enum is more efficient
than const. Here's a tested version.
template isIterable(T)
{
static if (is(typeof({foreach(elem; T.init) {}}))) {
enum bool isIterable = true;
} else {
enum bool isIterable = false;
}
}
import std.range; // For testing.
struct Foo { // For testing opApply.
// For testing.
int opApply(int delegate(ref uint) dg) { assert(0); }
}
static assert(isIterable!(uint[]));
static assert(!isIterable!(uint));
static assert(isIterable!(Foo));
static assert(isIterable!(uint[string]));
static assert(isIterable!(Chain!(uint[], uint[])));
More information about the Digitalmars-d
mailing list