Thread overview
static if with constant value
Dec 13, 2006
Bill Baxter
Dec 14, 2006
Bill Baxter
Dec 14, 2006
Sean Kelly
Dec 14, 2006
Bill Baxter
December 13, 2006
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
December 14, 2006
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
December 14, 2006
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
December 14, 2006
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