www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Widening a type

reply Doctor J <nobody nowhere.com> writes:
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?
Apr 16 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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
Apr 16 2009
parent BCS <none anon.com> writes:
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
 
Apr 16 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
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))
Apr 16 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
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;
Apr 17 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
Apr 17 2009