digitalmars.D.learn - No shortcircuit for static if or template constraints?
Hi All, Given this code: --- import std.traits; import std.range; import std.stdio; enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) { static if(isSupportedRange!T) { // Do something with a range } else { // Do something with a scalar } } void main() { int a1 = 0; int[] a2 = [1,2,3]; func(a1); func(a2); } --- I a compile error like so: ...std/traits.d(6136): Error: invalid foreach aggregate 0 hack.d(6): Error: template instance std.traits.ForeachType!int error instantiating hack.d(10): instantiated from here: isSupportedRange!int hack.d(22): instantiated from here: func!int However, if I remove the Foreach part the "isInputRange!T" clearly fails. I also tried overloading the function like so: --- enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) if(isSupportedRange!T) { // Do something with a range } void func(T)(T vals) if(isNumeric!T) { // Do something with a scalar } --- Again, if I remove the Foreach part and ignore element type of the range it works OK. Am I doing something wrong? Thanks, stew
Oct 24 2015
On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote:Hi All, Given this code: --- import std.traits; import std.range; import std.stdio; enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) { static if(isSupportedRange!T) { // Do something with a range } else { // Do something with a scalar } } void main() { int a1 = 0; int[] a2 = [1,2,3]; func(a1); func(a2); } --- I a compile error like so: ...std/traits.d(6136): Error: invalid foreach aggregate 0 hack.d(6): Error: template instance std.traits.ForeachType!int error instantiating hack.d(10): instantiated from here: isSupportedRange!int hack.d(22): instantiated from here: func!int However, if I remove the Foreach part the "isInputRange!T" clearly fails. I also tried overloading the function like so: --- enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) if(isSupportedRange!T) { // Do something with a range } void func(T)(T vals) if(isNumeric!T) { // Do something with a scalar } --- Again, if I remove the Foreach part and ignore element type of the range it works OK. Am I doing something wrong? Thanks, stewOh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly.
Oct 24 2015
On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote:On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote:Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType().[...]Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly.
Oct 24 2015
On Saturday, 24 October 2015 at 23:59:02 UTC, qsdfghjk wrote:On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote:Oh no! there's been a copy & paste error. I actually meant: --- enum isSupportedRange(T) = isInputRange!T && (isIntegral!(ElementType!T));On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote:Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType().[...]Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly.
Oct 24 2015
On Saturday, 24 October 2015 at 23:59:02 UTC, qsdfghjk wrote:On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote:Yep, that works, thanks! I also found I can do it with __traits, but I think your way is cleaner. enum bool isSupportedRange(T) = __traits(compiles, isInputRange!T && isIntegral!(ForeachType!T)); cheers, stewOn Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote:Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType().[...]Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly.
Oct 24 2015