Thread overview
Widening a type
Apr 17, 2009
Doctor J
Apr 17, 2009
Daniel Keep
Apr 17, 2009
BCS
Apr 17, 2009
Denis Koroskin
Apr 17, 2009
bearophile
April 17, 2009
OK, here's one for you that sounds like it ought to be easy, but I don't immediately see how to do it in a pretty way.

Given a type parameter T of a template:
If T is an integral type, I want to declare a variable 'widest' of type ulong;
If T is a floating-point type, I want to declare a variable 'widest' of type double.
And it has to be prettier than my solution.  :)

        static if (is (T: ulong))
            ulong widest = 0;
        else if (is (T: double))
            double widest = 0.0;
        else
            static assert (false, "Unimplemented type " ~ T.stringof) ;

Now, I thought this sounds like a great job for a mixin:

template Widen (T, alias varname)
{
    static if (is (T: ulong))
        ulong varname = 0;
    else if (is (T: double))
        double varname = 0.0;
    else
        static assert (false, "Unimplemented type " ~ T.stringof) ;
}

mixin Widen!(T, widest);

...but alas, "Declaration expected, not 'if'".

Help?


April 17, 2009

Doctor J wrote:
> OK, here's one for you that sounds like it ought to be easy, but I don't immediately see how to do it in a pretty way.
> 
> Given a type parameter T of a template:
> If T is an integral type, I want to declare a variable 'widest' of type ulong;
> If T is a floating-point type, I want to declare a variable 'widest' of type double.
> And it has to be prettier than my solution.  :)
> 
>         static if (is (T: ulong))
>             ulong widest = 0;
>         else if (is (T: double))
>             double widest = 0.0;
>         else
>             static assert (false, "Unimplemented type " ~ T.stringof) ;
> 
> Now, I thought this sounds like a great job for a mixin:
> 
> template Widen (T, alias varname)
> {
>     static if (is (T: ulong))
>         ulong varname = 0;
>     else if (is (T: double))
>         double varname = 0.0;
>     else
>         static assert (false, "Unimplemented type " ~ T.stringof) ;
> }
> 
> mixin Widen!(T, widest);
> 
> ....but alas, "Declaration expected, not 'if'".
> 
> Help?

The error tells you everything you need to know if you read it.

Actually, you have two problems: you're trying to use "if" where you should be using "static if", and you can't alias a symbol name then use it in a declaration.  Here's a fixed, expanded version.

template Widen (T, char[] varname)
{
    static if (is (T: ulong))
    {
        mixin(`ulong `~varname~` = 0;`);
    }
    else
    {
        static if (is (T: double))
        {
            mixin(`double `~varname~` = 0.0`);
        }
        else
        {
            static assert (false, "Unimplmented type " ~ T.stringof);
        }
    }
}

You can remove those braces, I just wanted to point out that putting "static" out the front of an "if" doesn't magically make the "else" branch static as well.

  -- Daniel
April 17, 2009
On Thu, Apr 16, 2009 at 10:11 PM, Doctor J <nobody@nowhere.com> wrote:

> template Widen (T, alias varname)
> {
>    static if (is (T: ulong))
>        ulong varname = 0;
>    else if (is (T: double))

else *static* if(is(T: double))
April 17, 2009
Hello Daniel,

> You can remove those braces, I just wanted to point out that putting
> "static" out the front of an "if" doesn't magically make the "else"
> branch static as well.
> 

I known what you are saying but that didn't read right to me: An if as a static if's else clause is not magically a static if. 

> -- Daniel
> 


April 17, 2009
On Fri, 17 Apr 2009 06:11:00 +0400, Doctor J <nobody@nowhere.com> wrote:

> OK, here's one for you that sounds like it ought to be easy, but I don't immediately see how to do it in a pretty way.
>
> Given a type parameter T of a template:
> If T is an integral type, I want to declare a variable 'widest' of type ulong;
> If T is a floating-point type, I want to declare a variable 'widest' of type double.
> And it has to be prettier than my solution.  :)
>
>         static if (is (T: ulong))
>             ulong widest = 0;
>         else if (is (T: double))
>             double widest = 0.0;
>         else
>             static assert (false, "Unimplemented type " ~ T.stringof) ;
>
> Now, I thought this sounds like a great job for a mixin:
>template Widen (T, alias varname)
> {
>     static if (is (T: ulong))
>         ulong varname = 0;
>     else if (is (T: double))
>         double varname = 0.0;
>     else
>         static assert (false, "Unimplemented type " ~ T.stringof) ;
> }
>
> mixin Widen!(T, widest);
>
> ...but alas, "Declaration expected, not 'if'".
>
> Help?
>
>

I would avoid mixin in such situation and use template instead:

template Widen(T)
{
   static if (is(T : ulong)) {
       alias ulong Widen;
   } else static if (is(T : double)) {
       alias double Widen;
   } else {
       static assert (false, "Unimplemented type " ~ T.stringof) ;
   }
}

Widen!(T) widest;

April 17, 2009
Doctor J:
> Given a type parameter T of a template:
> If T is an integral type, I want to declare a variable 'widest' of type ulong;
> If T is a floating-point type, I want to declare a variable 'widest' of type double.
> And it has to be prettier than my solution.  :)

A solution using my dlibs:

import std.stdio: writefln;
import d.templates: IsIntegral, IsType, If;

template Widened(T) {
    alias If!(IsIntegral!(T), ulong, If!(IsType!(T, float, double, real), double, void)) Widened;
}

void main() {
    writefln(typeid(Widened!(int))); // prints: ulong
    writefln(typeid(Widened!(byte))); // prints: ulong
    writefln(typeid(Widened!(real))); // prints: double
    writefln(typeid(Widened!(float))); // prints: double
    writefln(typeid(Widened!(double))); // prints: double

    writefln(typeid(Widened!(char))); // prints: void
    writefln(typeid(Widened!(string))); // prints: void
}

Note that real=>double and char=>void.
If you want char=>ulong, then you have to use another isType!(T, ...) instead of IsIntegral!(T).

dlibs (soon to be updated again to improve the apply()):
http://www.fantascienza.net/leonardo/so/libs_d.zip

Bye,
bearophile