On Wed, 25 Aug 2010 10:01:31 -0400, Andrej Mitrovic <andrej.mitrov...@gmail.com> wrote:

Ok I think I am kind of getting this. The template name inside a template is it's instantiation. I can do "CheckedInt.variable" and get back the value of "variable" in the current instantiation.

The trouble is, when you do a call like CheckedInt() you will loose all other data that you had before:

module binary_ops;

import std.stdio : writeln;
import std.traits;
import std.exception;

unittest
{
    auto foo = CheckedInt!(int)(5);
    auto bar = CheckedInt!(int)(5);
    foo.x = 4;
    bar.x = 5;

    foo = foo + bar;
   writeln(foo.x);     // writes 0
    writeln(bar.x);     // writes 5
}

void main() { }

struct CheckedInt(N) if (isIntegral!N)
{
    private N value;
    int x;
   this(N value)
    {
        this.value = value;
    }

    // addition
    CheckedInt opBinary(string op)(CheckedInt rhs) if (op == "+")
    {
        auto result = value + rhs.value;
       enforce(rhs.value >= 0 ? result >= value : result < value);
        return CheckedInt(result);
    }
}

Here I've lost the value of x. "return CheckedInt(result);" calls the constructor of the already instantiated template, but because of the way D works (afaik) it first has to deconstruct the object before constructing it again. And that includes initializing all members to their .init value before calling the constructor.

A struct is a value type, so you are making a copy regardless. Your expectation that foo = ... does not wholly replace foo is incorrect.

You could do this:

this(N value, int x)
{
   this.value = value;
   this.x = x;
}

...

return CheckedInt(result, x);

...

and then you're x comes through.

Value types are always passed by value unless you use pointers or ref.

BTW, this has nothing to do with CheckedInt being a shortcut for CheckedInt!N inside the instantiated template.

-Steve

Reply via email to