試しにこんなコードを書いて使ってみていたのですが、
template<typename O, typename T>
class Property {
O* owner;
T (O::*get)(void) const;
void (O::*set)(const T&);
public:
Property(O* _owner, T(O::*_get)(void) const, void (O::*_set)(const T&))
: owner(_owner), get(_get), set(_set) {}
operator T() const { return (owner->*get)(); }
void operator=(const T& value) { (owner->*set)(value); }
};
こんなコード
class A {
int a;
void set(const int& _x) { a = _x; }
int get() const { return a; }
public:
Property<A,int> x;
A() : x(this,&A::get,&A::set) {}
};
を書いてみると
A a,b;
a.x = 1;
b.x = a.x; // → "b.x = 1"
a.x = 2; // → "b.x = 2" !!
という世にも恐ろしい結果が! (((( ;゚Д゚))))しばらく悩んで、浅はかにも「コンパイラのバグ?」なんて思ったりもしたのですが、よく考えると"b.x = a.x;"の所で(いやここしか考えられないのですが)デフォルトコピーコンストラクタがメンバ変数全部(母屋へのポインタ)をコピーしていた所為 orz
こんな感じに
Property(const Property<O,T>& p)
: owner(p._owner), get(p._get), set(p._set) {}
void operator=(const T& value) { (owner->*set)(value); }
void operator=(const Property<O,T>& p) { (owner->*set)(p.value()); }
コードを書き足しすと…ちゃんと期待通りの動作をするようになりました。 ( ´∀`)…単にねこさんの修行が足りてないだけなのですが orz
0 件のコメント:
コメントを投稿