Creating a subtype using struct template
This recipe shows how to create a subtype for an integral / floating point range using a struct template. Run the code
Program Code
import std.traits : isIntegral, isFloatingPoint;
struct SubType(Type, Type Min, Type Max, Type Init = Min, alias Ex = Exception,
alias Tolerance = 0.001f)
if( isIntegral!(Type) || isFloatingPoint!(Type) )
{
private
{
Type value = Init;
}
//static const Type min = Min;
//static const Type max = Max;
@property Type access()
{
return value;
}
@property void access(Type new_val)
{
static if (isIntegral!(Type))
{
if ( !((new_val >= Min) && (new_val <= Max)) )
throw new Ex("Value not in range [min,max]");
}
else static if (isFloatingPoint!(Type))
{
Type amin = new_val - Min;
amin = (amin < 0.0)? -amin : amin;
Type amax = new_val - Max;
amax = (amax < 0.0)? -amax : amax;
if ( !( ((new_val > Min) || (amin < Tolerance)) &&
((new_val < Max) || (amax < Tolerance)) ) )
throw new Ex("Value not in range [min,max]");
}
else
static assert(false, "Not Implemented!");
value = new_val;
}
alias access this;
}
class MyException : Exception
{
this(string msg, string f = __FILE__, size_t l = __LINE__)
{
super( "MyException: " ~ msg, f, l);
}
}
//pragma(msg, SubType!(int, 0, 123).max );
unittest
{
import std.conv : to;
import std.exception : assertThrown;
alias SubType!(int, 0, 123, 100, MyException) MyInt1;
alias SubType!(int, 0, 123) MyInt2;
MyInt1 m1;
MyInt2 m2;
assert(m1 == 100);
assert(m2 == 0);
m1 = 123;
assert(m1 == 123);
m2 = to!(uint)("123");
assert(m2 == 123);
assertThrown!(MyException)(m1 = -1);
assertThrown!(MyException)(m1 = 124);
m1 = 99;
assert(m1 == 99);
assertThrown(m2 = -1);
assertThrown(m2 = 124);
m2 = 99;
assert(m2 == 99);
SubType!(float, 0.0, 1.0) f1;
const float tol = 0.001f;
float diff;
diff = f1 - 0.0f;
diff = (diff < 0.0f)? -diff : diff;
assert(diff < tol);
f1 = 1.0f;
diff = f1 - 1.0f;
diff = (diff < 0.0f)? -diff : diff;
assert(diff < tol);
assertThrown(f1 = -0.01f);
assertThrown(f1 = 1.01f);
SubType!(double, 0.000_1, 0.000_9, 0.000_1, MyException, 0.000_001) d1;
const double dtol = 0.000_001;
double ddiff;
ddiff = d1 - 0.000_1;
ddiff = (ddiff < 0)? -ddiff : ddiff;
assert(ddiff < dtol);
d1 = 0.000_9;
ddiff = d1 - 0.000_9;
ddiff = (ddiff < 0)? -ddiff : ddiff;
assert(ddiff < dtol);
assertThrown!(MyException)(d1 = 0.000_09);
assertThrown!(MyException)(d1 = 0.000_099);
assertThrown!(MyException)(d1 = 0.000_91);
assertThrown!(MyException)(d1 = 0.000_901);
d1 = 0.000_0999;
ddiff = d1 - 0.000_0999;
ddiff = (ddiff < 0)? -ddiff : ddiff;
assert(ddiff < dtol);
d1 = 0.000_9001;
ddiff = d1 - 0.000_9001;
ddiff = (ddiff < 0)? -ddiff : ddiff;
assert(ddiff < dtol);
}
void main() { }
Facts about "Creating a subtype using struct template"
Cookbook/Status | Draft + |
Cookbook/Type | Recipe + |
D Version | D2 + |
Level | Novice + |
Read time | 5 min (0.083 hr) + |