www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - static if with constant value

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
I can't understand why the little program below outputs what it does.
It seems like static if (constant) works in some cases but not others. 
Is this just a bug?

----
import std.stdio : writef, writefln;

template is_complex(T)
{
     static if (is(typeof(T.init.re)) && is(typeof(T.init.im))) {
         const bool is_complex = true;
     } else {
         const bool is_complex = false;
     }
}
template float_for_type(T)
{
     static if ( is_complex!(T) ) {
         alias typeof(T.init.re) float_for_type;
     } else {
         alias T float_for_type;
     }
}

void print_complex(T)(T* arg)
{
     static const bool cplx = is_complex!(T);
     writefln("print_complex: Type: %s, is_complex? ", typeid(T), cplx);
     static if ( is_complex!(T) ) {
         writefln("print_complex: static if is_complex? true");
     } else {
         writefln("print_complex: static if is_complex? false");
     }
}


void main()
{
     float f;
     cfloat c;
     double d;
     cdouble z;
     writefln("main: %s made from %s", typeid(typeof(f)), 
typeid(float_for_type!(typeof(f)))); print_complex(&f);
     writefln("main: %s made from %s", typeid(typeof(c)), 
typeid(float_for_type!(typeof(c)))); print_complex(&c);
     writefln("main: %s made from %s", typeid(typeof(d)), 
typeid(float_for_type!(typeof(d)))); print_complex(&d);
     writefln("main: %s made from %s", typeid(typeof(z)), 
typeid(float_for_type!(typeof(z)))); print_complex(&z);
}
----


Here's what it outputs for me with DMD:

main: float made from float
print_complex: Type: float, is_complex? true
print_complex: static if is_complex? true
main: cfloat made from float
print_complex: Type: cfloat, is_complex? true
print_complex: static if is_complex? true
main: double made from double
print_complex: Type: double, is_complex? true
print_complex: static if is_complex? true
main: cdouble made from double
print_complex: Type: cdouble, is_complex? true
print_complex: static if is_complex? true


In float_for_type!(T), is_complex!(T) works, but in print_complex it 
does not for some reason (it always evaluates to true).   Can anyone 
explain this behavior?

--bb
Dec 13 2006
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Doh, I figured out why it does what it does now.  I had assumed that 
floats and doubles didn't have .re and .im properties, so that that 
would cause the is() check to fail.

So what's a better way to check for complexity of a type?
I'd rather not have to list every complex type explicitly.  It's ugly 
for one, but more importantly it precludes recognizing user types as 
complex-like.

Maybe this is close enough?

    static if( is(T:cfloat) || is(T:cdouble) || is(T:creal) ) {...}

--bb

Bill Baxter wrote:
 I can't understand why the little program below outputs what it does.
 It seems like static if (constant) works in some cases but not others. 
 Is this just a bug?
 
 ----
 import std.stdio : writef, writefln;
 
 template is_complex(T)
 {
     static if (is(typeof(T.init.re)) && is(typeof(T.init.im))) {
         const bool is_complex = true;
     } else {
         const bool is_complex = false;
     }
 }
 template float_for_type(T)
 {
     static if ( is_complex!(T) ) {
         alias typeof(T.init.re) float_for_type;
     } else {
         alias T float_for_type;
     }
 }
 
 void print_complex(T)(T* arg)
 {
     static const bool cplx = is_complex!(T);
     writefln("print_complex: Type: %s, is_complex? ", typeid(T), cplx);
     static if ( is_complex!(T) ) {
         writefln("print_complex: static if is_complex? true");
     } else {
         writefln("print_complex: static if is_complex? false");
     }
 }
 
 
 void main()
 {
     float f;
     cfloat c;
     double d;
     cdouble z;
     writefln("main: %s made from %s", typeid(typeof(f)), 
 typeid(float_for_type!(typeof(f)))); print_complex(&f);
     writefln("main: %s made from %s", typeid(typeof(c)), 
 typeid(float_for_type!(typeof(c)))); print_complex(&c);
     writefln("main: %s made from %s", typeid(typeof(d)), 
 typeid(float_for_type!(typeof(d)))); print_complex(&d);
     writefln("main: %s made from %s", typeid(typeof(z)), 
 typeid(float_for_type!(typeof(z)))); print_complex(&z);
 }
 ----
 
 
 Here's what it outputs for me with DMD:
 
 main: float made from float
 print_complex: Type: float, is_complex? true
 print_complex: static if is_complex? true
 main: cfloat made from float
 print_complex: Type: cfloat, is_complex? true
 print_complex: static if is_complex? true
 main: double made from double
 print_complex: Type: double, is_complex? true
 print_complex: static if is_complex? true
 main: cdouble made from double
 print_complex: Type: cdouble, is_complex? true
 print_complex: static if is_complex? true
 
 
 In float_for_type!(T), is_complex!(T) works, but in print_complex it 
 does not for some reason (it always evaluates to true).   Can anyone 
 explain this behavior?
 
 --bb

Dec 13 2006
parent reply Sean Kelly <sean f4.ca> writes:
Bill Baxter wrote:
 Doh, I figured out why it does what it does now.  I had assumed that 
 floats and doubles didn't have .re and .im properties, so that that 
 would cause the is() check to fail.
 
 So what's a better way to check for complexity of a type?
 I'd rather not have to list every complex type explicitly.  It's ugly 
 for one, but more importantly it precludes recognizing user types as 
 complex-like.
 
 Maybe this is close enough?
 
    static if( is(T:cfloat) || is(T:cdouble) || is(T:creal) ) {...}

You can probably just do: static if( is(T:creal) ) { ... } As far as I know, cfloat and cdouble are convertible to creal, so that should work. I personally chose to list types in the traits templates I created, but that is because I want to be sure that they're exactly that type. I generally don't want UDTs filtering through as well. Sean
Dec 13 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Sean Kelly wrote:
 Bill Baxter wrote:
 Doh, I figured out why it does what it does now.  I had assumed that 
 floats and doubles didn't have .re and .im properties, so that that 
 would cause the is() check to fail.

 So what's a better way to check for complexity of a type?
 I'd rather not have to list every complex type explicitly.  It's ugly 
 for one, but more importantly it precludes recognizing user types as 
 complex-like.

 Maybe this is close enough?

    static if( is(T:cfloat) || is(T:cdouble) || is(T:creal) ) {...}

You can probably just do: static if( is(T:creal) ) { ... } As far as I know, cfloat and cdouble are convertible to creal, so that should work. I personally chose to list types in the traits templates I created, but that is because I want to be sure that they're exactly that type. I generally don't want UDTs filtering through as well. Sean

Yeh, that makes sense. I think I'm going to need both kinds of tests eventually, actually. --bb
Dec 13 2006