type set

spir denis.spir at gmail.com
Mon Feb 28 06:27:36 PST 2011


On 02/28/2011 02:32 PM, Steven Schveighoffer wrote:
> On Mon, 28 Feb 2011 08:22:58 -0500, spir <denis.spir at gmail.com> wrote:
>
>> Hello,
>>
>> I have a template condition that looks like this:
>>
>> T check (T) () if (
>> is(T == DLogical) ||
>> is(T == DNumber) ||
>> is(T == DText) ||
>> is(T == DList) ||
>> is(T == DUnit)
>> ) {
>> ...
>> }
>>
>> Is there a way to "factor out" such an expression using a kind of type set?
>> If only for cleaning the code; but also because such a set may get long.
>>
>> T check (T) () if (is (T in validTypeSet)) {
>> ...
>> }
>
> This should probably work:
>
> template isOneOf(X, T...)
> {
> static if(!T.length)
> enum bool isOneOf = false;
> else static if(is(X == T[0]))
> enum bool isOneOf = true;
> else
> enum bool isOneOf = isOneOf!(X, T[1..$]);
> }
>
> T check(T) () if(isOneOf!(T, DLogical, DNumber, DText, TList, DUnit))
> {
> ...
> }
>
> Not sure if this exists in std.traits or not, but that's where I'd look.
>
> -Steve

Waow, great anyway! Didn't even know one can write variadic type/template param 
lists.

By the way, the block of the function is a series of static if-s, one for each 
allowed type. Is there any static switch? Or any other nicer way to write it than:

     T check (T) () if (
             is(T == DLogical) ||
             is(T == DNumber) ||
             is(T == DText) ||
             is(T == DList) ||
             is(T == DUnit)
         ) {
         TypeCode type;

         static if (is(T == DLogical))
             if (this.code == LOGICAL)
                 return this.logical;
             else
                 type == LOGICAL;
         static if (is(T == DNumber))
             if (this.code == NUMBER)
                 return this.number;
             else
                 type == NUMBER;
         static if (is(T == DText))
             if (this.code == TEXT)
                 return this.text;
             else
                 type == TEXT;
         static if (is(T == DList))
             if (this.code == LOGICAL)
                 return this.list;
             else
                 type == LOGICAL;
         static if (is(T == DUnit))
             if (this.code == UNIT)
                 return this.unit;
             else
                 type == UNIT;

         // type error
         throw new TypeError(type, this);
     }

This func type-checks and returns the current value of a tagged union. I would 
be very pleased with a mapping from types to type codes (tags). I can't do 
without the type param, I guess, because it's the return value's type... or can 
I? But the discriminating code of the union cannot be the type itself (*), 
instead it's a plain code.
I thought at using TypeInfo-s as codes, which can then be mapped from types 
using typeid(). But according to sizeof, this makes the code weigh 1 word 
instead of one byte.

Denis

(*) Indeed. Else it would be a template generating N distinct types, which is 
precisely the opposite of what a union provides.
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list