C++ to D
John Colvin via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Wed Apr 1 11:13:49 PDT 2015
On Wednesday, 1 April 2015 at 17:51:40 UTC, John Colvin wrote:
> On Wednesday, 1 April 2015 at 17:03:34 UTC, Dennis Ritchie
> wrote:
>> On Wednesday, 1 April 2015 at 15:22:10 UTC, John Colvin wrote:
>>> Compile Time Function Evaluation (CTFE) is a very powerful
>>> tool
>>> to avoid having to enter in to all that C++ style mess.
>>
>> Yes, CTFE in D really cool. Thanks.
>>
>> I need to implement arithmetic (addition / subtraction) only
>> use the type system.
>> That is, such a design does not suit me:
>>
>> enum Add(Args...) = Args[0] + Args[1];
>> enum Inc(Args...) = Args[0] + 1;
>
> Don't really see the point. Here's a neat thing that's
> definitely cheating because although it stores the results in
> the type system, the arithmetic is done in constant-folding:
>
> struct Integer(int a){}
> template Value(T)
> {
> static if (is(T == Integer!a, int a))
> enum Value = a;
> else static assert(false, "Can't get Value for " ~
> T.stringof);
> }
> alias Inc(T) = Integer!(Value!T + 1);
>
>
> But if you really insist on it being all type-system (until you
> wan't the answer of course):
>
> struct Zero{}
>
> template Succ(T)
> {
> static if (is(T == Pred!A, A))
> alias Succ = A;
> else
> struct Succ{}
> }
>
> template Pred(T)
> {
> static if (is(T == Succ!A, A))
> alias Pred = A;
> else
> struct Pred{}
> }
>
> enum isPositive(T) = is(T == Succ!A, A);
> enum isNegative(T) = is(T == Pred!A, A);
> enum isZero(T) = is(T == Zero);
>
> template Add(A, B)
> {
> static if (isZero!B)
> alias Add = A;
> else static if (isPositive!B)
> alias Add = Add!(Succ!A, Pred!B);
> else
> alias Add = Add!(Pred!A, Succ!B);
> }
>
> template Value(T, int seed = 0)
> {
> static if (isZero!T)
> enum Value = seed;
> else static if (isPositive!T)
> enum Value = Value!(Pred!T, seed+1);
> else
> enum Value = Value!(Succ!T, seed-1);
> }
>
> unittest
> {
> alias One = Succ!Zero;
> alias Two = Succ!One;
> alias MinusThree = Pred!(Pred!(Pred!Zero));
>
> static assert (Value!Zero == 0);
> static assert (Value!One == 1);
> static assert (Value!Two == 2);
> static assert (Value!MinusThree == -3);
>
> static assert (Value!(Add!(One, MinusThree)) == -2);
> static assert (Value!(Add!(One, Two)) == 3);
> static assert (is(Add!(Add!(One, Two), MinusThree) == Zero));
> }
If the is() expressions are confusing you, in this case they work
like this;
is (T == B!A, A)
means
is T the same type as B instantiated with A, for some type A?
or more succinctly
is T an instantiation of B?
See http://dlang.org/expression.html#IsExpression, it's quite
reminiscent of some mathematical set notation.
More information about the Digitalmars-d-learn
mailing list