opAssign and template class

Stanislav Blinov stanislav.blinov at gmail.com
Wed Feb 5 05:46:14 PST 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.


More information about the Digitalmars-d mailing list