Not sure if this is a bug or intended behavior:

import std.traits;
struct S {
     int i;
     T opCast(T)() if(isFloatingPoint!T) {
         return cast(T)i;
     }
}

template myIsFloatingPoint(T) {
     enum myIsFloatingPoint =  isFloatingPoint!T
         || __traits(compiles, { cast(real)T.init; });
}

void main() {
     auto s = S(10);
     assert(cast(real)s == 10.0);
     // static assert( isFloatingPoint!S); // false
     static assert( myIsFloatingPoint!S);
     static assert( myIsFloatingPoint!float);
     static assert(!myIsFloatingPoint!int);
}


Think of a Fraction or RangedInt struct for instance:

import std.traits;

struct Ranged(T, T minValue, T maxValue)
     if(isNumeric!T)
{
     enum T max = maxValue;
     enum T min = minValue;
     T value = min;

     invariant() {
         assert(value >= min && value <= max);
     }

     T opCast()() {
         return value;
     }

     void opAssign(T value) {
         this.value = value;
     }

     bool opEquals(T value) {
         return this.value == value;
     }
}

void f(int v) {}

void g(T)(T v) if(isNumeric!T) {
}

void main() {
     Ranged!(int, 10, 20) v;
     assert(v == 10);
     v = 20;
     //v = 21; // assert as expected
     // f(v); // ok if we would use an alias this, but then the
Ranged isn't in effect anymore
     //g(v); // oops.. Ranged is not numeric

}

So.. What do I need to implement for a struct to be a valid
built-in type?
All valid properties (min, max etc) and operators for that type?

Reply via email to