How to "extend" built-in types

simendsjo simendsjo at gmail.com
Sat Oct 27 03:34:28 PDT 2012


On Saturday, 27 October 2012 at 10:07:20 UTC, Jonathan M Davis 
wrote:
> On Saturday, October 27, 2012 11:58:57 simendsjo wrote:
>> The thing is that I often doesn't really care about the type,
>> only that it exposes certain properties.
>
> Then create a template constraint (or eponymous template to use 
> in a template
> constraint) which tests for those properties. That's exactly 
> what templates
> like isForwardRange and hasLength do for range-based 
> operations. You just need
> the same sort of thing for the set operations that you require.

So something like this then?
Should the traits module be extended with templates to query for 
certain behavior?

template hasDivision(T) {
     enum hasDivision = isNumeric!T || __traits(compiles, 
{T.init/1;});
}

template castsTo(T, C) {
     enum castsTo = __traits(compiles, {cast(C)T.init;});
}

template castsToIntegral(T) {
     enum castsToIntegral =
            castsTo!(T, byte)  || castsTo!(T, ubyte)
         || castsTo!(T, short) || castsTo!(T, ushort)
         || castsTo!(T, int)   || castsTo!(T, uint)
         || castsTo!(T, long)  || castsTo!(T, ulong);
}

template hasIntegerDivision(T) {
     enum hasIntegerDivision = isIntegral!T
         || (hasDivision!T && castsToIntegral!(typeof(T.init/2)));
}
unittest {
     assert( hasIntegerDivision!int);
     assert(!hasIntegerDivision!float);

     struct Int {
         int i;
         Int opBinary(string op, T)(T value) if(isIntegral!T && op 
== "/") {
             return Int(i/value);
         }

         T opCast(T)() if(isIntegral!T) {
             return cast(T)i;
         }
     }

     assert( hasIntegerDivision!Int);
}




More information about the Digitalmars-d-learn mailing list