19:00 余計な処理を入れていたみたいなので削除しました.
今のD言語では opAssign(T)() が定義できないらしい.
どうもD言語の shared_ptr に boost::shared_ptr のような多態性を持たせるのは無理な気がするがどうなんだろう.
とりあえず上記のことはD言語の仕様として諦めた.
カウンタをstaticメンバにしたらオブジェクトとカウンタの対応関係を作らないといけなくなったので連想配列を使用する shared_ptr を作ったw
あとスレッドアンセーフ.
よくわからないけどこんなもんなのかなあ.
ソースは続きに.
import std.stdio; struct shared_ptr(T) if(is(T == class)) { private: static int n[T]; T p; alias p this; public: static shared_ptr!T opCall(U)(U p) { shared_ptr!T ret; ret.p = p; ret.n[p]++; debug writefln("opCall(T) ", ret.n[p]); return ret; } this(this) { n[p]++; debug writeln("postblit ", n[p]); } ref shared_ptr!T opAssign(shared_ptr!T t) { p = t.p; n[p]++; debug writeln("opAssign ", n[p]); return this; } ~this() { n[p]--; debug writeln("dtor ", n[p]); assert(n[p] >= 0); if(n[p] == 0) { delete p; debug writeln("deleted"); } } } class A { void f() {writeln("I am A.");} this() { writeln("A.this"); } ~this() { writeln("A.~this"); } } class B : A { void f() {writeln("I am B.");} this() { writeln("B.this"); } ~this() { writeln("B.~this"); } } scope class C // 実験のためCはscope { shared_ptr!A sa; this(shared_ptr!A sa) { this.sa = sa; assert(shared_ptr!A.n[sa.p] == 2); } } shared_ptr!A g; void set(A a) { assert(shared_ptr!A.n[a] == 0); auto x = shared_ptr!A(a); assert(shared_ptr!A.n[a] == 1); g = x; assert(shared_ptr!A.n[a] == 2); } void main() { writeln("\n* 1. opCall(shared_ptr!T) and postblit *"); { auto a = new A; auto sa = shared_ptr!A(a); // opCall assert(shared_ptr!A.n[a] == 1); auto sb = sa; // postblit assert(shared_ptr!A.n[a] == 2); sa.f(); sb.f(); } writeln("\n* 2. opAssign(shared_ptr!T) *"); { auto a = new A; shared_ptr!A sa; sa = shared_ptr!A(a); // opAssign assert(shared_ptr!A.n[a] == 1); sa.f(); } writeln("\n* 3. polymorphic with opCall *"); { auto b = new B; shared_ptr!A sa = shared_ptr!B(b); // polymorphic with opCall assert(shared_ptr!A.n[b] == 1); assert(shared_ptr!B.n[b] == 1); sa.f(); } writeln("\n* 4. polymorphic with opAssign *"); { // opAssign(T t)とopAssign(U)(U u)がconflictすると言われて // 定義することができないので無理? // auto b = new B; // shared_ptr!A sa; // sa = shared_ptr!B(b); // polymorphic with opAssign // assert(shared_ptr!A.n[b] == 1); // assert(shared_ptr!B.n[b] == 1); // sa.f(); } writeln("\n* 5. polymorphic with function call *"); { // 同様にむりぽ // void polySet(shared_ptr!A sa) // { // assert(shared_ptr!A.n[sa.p] == 2); // } // auto sb = shared_ptr!B(new B); // polySet(sb); // assert(shared_ptr!A.n[sb.p] == 1); // assert(shared_ptr!B.n[sb.p] == 1); } writeln("\n* 6. class member *"); { auto a = new A; scope c = new C(shared_ptr!A(a)); assert(shared_ptr!A.n[a] == 1); scope d = c; assert(shared_ptr!A.n[a] == 1); // dは参照なので1でいいはず } writeln("\n* 7. global *"); { auto a = new A; set(a); assert(shared_ptr!A.n[a] == 1); } writeln("\n<-- the end of main"); } static ~this() { assert(g.n[g.p] == 1); // まだ残っている writeln("\n<-- the end of static ~this"); }
追加
実行結果を載せ忘れてた.
* 1. opCall(shared_ptr!T) and postblit * A.this opCall(T) postblit 2 dtor 1 postblit 2 I am A. I am A. dtor 1 dtor 0 A.~this deleted * 2. opAssign(shared_ptr!T) * A.this opCall(T) postblit 2 dtor 1 opAssign 2 dtor 1 I am A. dtor 0 A.~this deleted * 3. polymorphic with opCall * A.this B.this opCall(T) postblit 2 dtor 1 opCall(T) postblit 2 dtor 1 I am B. dtor 0 B.~this A.~this deleted * 4. polymorphic with opAssign * * 5. polymorphic with function call * * 6. class member * A.this opCall(T) postblit 2 dtor 1 postblit 2 opAssign 3 dtor 2 dtor 1 dtor 0 A.~this deleted * 7. global * A.this opCall(T) postblit 2 dtor 1 postblit 2 opAssign 3 dtor 2 dtor 1 <-- the end of main <-- the end of static ~this A.~this