digitalmars.D - isIterable(T)
- dsimcha (11/11) Apr 26 2009 I've been thinking a little more about ranges, etc. and it would be nice...
- Denis Koroskin (10/27) Apr 26 2009 // Not tested
- dsimcha (23/52) Apr 26 2009 Wow, IDK why I thought that wouldn't work. I must have made some minor
- bearophile (7/9) Apr 26 2009 I agree.
- dsimcha (24/33) Apr 26 2009 you are going to think tomorrow and the day after tomorrow.
- bearophile (4/6) Apr 26 2009 See BaseType and BaseType1 in my "templates" module (I think you are tal...
- dsimcha (6/12) Apr 26 2009 about BaseType1 here, later you will probably feel the need of BaseType ...
- downs (2/14) Apr 27 2009 See title :)
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.
Apr 26 2009
On Sun, 26 Apr 2009 21:44:31 +0400, dsimcha <dsimcha 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; } }
Apr 26 2009
== Quote from Denis Koroskin (2korden gmail.com)'s articleOn Sun, 26 Apr 2009 21:44:31 +0400, dsimcha <dsimcha yahoo.com> wrote: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[])));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; } }
Apr 26 2009
dsimcha Wrote:I've been thinking a little more about ranges, etc. and it would be nice to have a template for isIterable(T)I agree. IsIterable is already inside my dlibs (as the xkeys/xvalues you talk about in another post of yours, but in the "func" module), into the "templates" module: http://www.fantascienza.net/leonardo/so/dlibs/templates.html I suggest you to take a good look at those dlibs, you will probably find stuff you are going to think tomorrow and the day after tomorrow. Bye, bearophile
Apr 26 2009
== Quote from bearophile (bearophileHUGS lycos.com)'s articledsimcha Wrote:another post of yours, but in the "func" module), into the "templates" module:I've been thinking a little more about ranges, etc. and it would be nice to have a template for isIterable(T)I agree. IsIterable is already inside my dlibs (as the xkeys/xvalues you talk about inhttp://www.fantascienza.net/leonardo/so/dlibs/templates.html I suggest you to take a good look at those dlibs, you will probably find stuffyou are going to think tomorrow and the day after tomorrow.Bye, bearophileThanks. The other part of the question, which all of us seemed to neglected was how to get the type of elem. I just got that to work, too. import std.traits, std.range; template IterType(T) { alias ReturnType!( { foreach(elem; T.init) { return elem; } }) IterType; } unittest { struct Foo { // For testing opApply. // For testing. int opApply(int delegate(ref uint) dg) { assert(0); } } static assert(is(IterType!(uint[]) == uint)); static assert(is(IterType!(Foo) == uint)); static assert(is(IterType!(uint[string]) == uint)); static assert(is(IterType!(Chain!(uint[], uint[])) == uint)); }
Apr 26 2009
dsimcha:Thanks. The other part of the question, which all of us seemed to neglected was how to get the type of elem.See BaseType and BaseType1 in my "templates" module (I think you are talking about BaseType1 here, later you will probably feel the need of BaseType too, so I avoid posting another post later). Bye, bearophile
Apr 26 2009
== Quote from bearophile (bearophileHUGS lycos.com)'s articledsimcha:about BaseType1 here, later you will probably feel the need of BaseType too, so I avoid posting another post later).Thanks. The other part of the question, which all of us seemed to neglected was how to get the type of elem.See BaseType and BaseType1 in my "templates" module (I think you are talkingBye, bearophileThanks. I haven't looked at your dlibs much, mostly because they're supposed to be for D1, and all my code is in D2. I guess there are some good template code snippets that generalize to D2 in there, though.
Apr 26 2009
bearophile wrote:dsimcha Wrote:See title :)I've been thinking a little more about ranges, etc. and it would be nice to have a template for isIterable(T)I agree. IsIterable is already inside my dlibs (as the xkeys/xvalues you talk about in another post of yours, but in the "func" module), into the "templates" module: http://www.fantascienza.net/leonardo/so/dlibs/templates.html I suggest you to take a good look at those dlibs, you will probably find stuff you are going to think tomorrow and the day after tomorrow. Bye, bearophile
Apr 27 2009