Thread overview
opAssign and template class
Feb 05, 2014
dbjdbj
Feb 05, 2014
Stanislav Blinov
Feb 05, 2014
dbjdbj
Feb 05, 2014
Stanislav Blinov
Feb 05, 2014
dbjdbj
Feb 05, 2014
Stanislav Blinov
Feb 05, 2014
dbjdbj
Feb 05, 2014
Ali Çehreli
February 05, 2014
Please consider this: http://dpaste.dzfl.pl/dc4a3c29e57f

What is my mistake ?

Thanks ...
February 05, 2014
On Wednesday, 5 February 2014 at 10:33:08 UTC, dbjdbj wrote:
>
> Please consider this: http://dpaste.dzfl.pl/dc4a3c29e57f
>
> What is my mistake ?
>
> Thanks ...

You cannot overload identity assignment for classes. It's a language construct that rebinds a reference and cannot be overridden. Such opAssign overloading is only possible for structs.

See http://dlang.org/operatoroverloading.html#Assignment.

February 05, 2014
>
> You cannot overload identity assignment for classes. It's a language construct that rebinds a reference and cannot be overridden. Such opAssign overloading is only possible for structs.
>
> See http://dlang.org/operatoroverloading.html#Assignment.

I need to be able to implement "=" operator so that this works:

auto x_ = new X(), x2 = x_ ;

objects)alive needs to be 2 after.

Thanks ...
February 05, 2014
On Wednesday, 5 February 2014 at 12:29:11 UTC, dbjdbj wrote:

> I need to be able to implement "=" operator so that this works:
>
> auto x_ = new X(), x2 = x_ ;
>
> objects)alive needs to be 2 after.
>
> Thanks ...

You can't. Classes are reference types. This just doesn't make sense: x2 = x_; does not create any new objects.
February 05, 2014
>
> You can't. Classes are reference types. This just doesn't make sense: x2 = x_; does not create any new objects.

*object_alive* is what I mentioned, not object_create

therefore it does "make sense" ...  so  here it is again:

auto x_ = new X() , // created:1 , alive: 1
     x2 = x_      ; // created:1 , alive: 2

I tried (in all of my D innocence) to implement simple but effective counter from C++ side of the "wall" ... using the CRTP idiom ...





February 05, 2014
On Wednesday, 5 February 2014 at 13:38:08 UTC, dbjdbj wrote:
>
>>
>> You can't. Classes are reference types. This just doesn't make sense: x2 = x_; does not create any new objects.
>
> *object_alive* is what I mentioned, not object_create

Yes, but in your implementation you intend to increment both counters in opAssign.

> therefore it does "make sense" ...  so  here it is again:
>
> auto x_ = new X() , // created:1 , alive: 1
>      x2 = x_      ; // created:1 , alive: 2
>
> I tried (in all of my D innocence) to implement simple but effective counter from C++ side of the "wall" ... using the CRTP idiom ...

You just cannot reliably count references to class objects in D (at least, yet, see the ongoing discussions: http://forum.dlang.org/thread/lcrue7$1ho3$1@digitalmars.com, http://forum.dlang.org/thread/grngmshdtwqfaftefhky@forum.dlang.org).

For non-class objects, there is a library implementation, std.typecons.RefCounted.

With it, you can roll something similar:

import std.stdio;
import std.typecons;

struct Counter(T) if (!is(T == class)) {
    @disable this(this);
    @disable void opAssign(ref Counter);

    private static int objectsCreated_ = 0;
    private T x_;

    this(T x) { x_ = x; ++objectsCreated_; }

    static int getObjectsCreated() { return objectsCreated_; }

    @property ref auto get() inout { return x_; }

    alias get this;
}

auto counter(T,Args...)(ref auto Args args) if (!is(T == class)) {
    return RefCounted!(Counter!T)(T(args));
}

@property auto objectsCreated(O)(ref O o) if (is(O == RefCounted!(Counter!T), T)) {
    return o.getObjectsCreated();
}

@property auto numReferences(O)(ref O o) if (is(O == RefCounted!(Counter!T), T)) {
    return o.refCountedStore.refCount;
}

struct X { int v; }
struct Y { string s; }

void foo(ref const X x) {
    writefln("%s", x.v);
}

void bar(ref const Y y) {
    writefln("%s", y.s);
}

void main()
{
    auto x_ = counter!X, x2 = x_;
    writefln("objects created: %s, num references: %s", x_.objectsCreated, x_.numReferences);
    foo(x_);

    auto y_ = counter!Y("hello"), y2 = y_;
    y2.s = "world"; // Modifies y_.s too
    writefln("objects created: %s, num references: %s", y_.objectsCreated, y_.numReferences);
    bar(y_);
}


---

Note that e.g. typeof(x_) is actually RefCounted!(Counter!X).

But you cannot do similar for classes, because you cannot guard against escaping references.
February 05, 2014
Impressive but please next time please use: http://dpaste.dzfl.pl/ ...

Depressive is this issue (and some more) since I was sincerely hoping I could live C++ "behind" ...

Eh ...


February 05, 2014
On 02/05/2014 09:37 AM, dbjdbj wrote:>
> Impressive but please next time please use: http://dpaste.dzfl.pl/ ...

I disagree. dpaste has no association with this newsgroup and can disappear at any time in the future.

>
> Depressive is this issue (and some more) since I was sincerely hoping I
> could live C++ "behind" ...
>
> Eh ...

There is a significant difference between D and C++. In D, classes are reference types (not value types).

The equivalent in C++ of what you are trying to do would be overriding the assignment operator for class pointers, which is not possible in C++:

// C++ code:
X * x_ = new X() , // created:1 , alive: 1
  * x2 = x_      ; // created:1 , alive: 2 (not possible!)

Same limitation in D...

Ali