2014-05-02-01-本気で move について考える - 5
>> Site top >> weblog >> 月別アーカイブ >> 2014年05月のlog >> 2014-05-02-01-本気で move について考える - 5
最終更新日付:2014/05/02 01:00:00
本気で move について考える - 5
2014 年 05 月 02 日
行き詰まった感じが募ってくると、「まぁ手を動かしてみようや」とか考えてしまうのはいくつになっても直らない。そんなわけで、結局 operator-move とかは中途半端に実装してしまった。もちろん、前回書いたような悩みは継続しているわけで。
ひとまずのところ、もういい加減 move および代入について悩むのはやめようかと思っている。Common Lisp は Lisp なのであって、その上に C++ を構築することはできないし、そうすべきでもない。自分は Common Lisp 上で使える STL が欲しいのであって、C++ が使いたいならば C++ を使うべきなのだ。そんなわけで、現時点でわかっていることだけでもやってみて、それで手打ちにしようと考えている。
で、総称関数のメソッドについて。:before とか :after だとかを調べていくうち、 :around が役に立つのではないか、ということがわかってきた。前回のコードに関して言えば、第2パラメータを remove-reference で特定化するメソッドについてのみ :around 指定をしてやれば、標準のメソッドよりは優先されてくれるようなのだ。 前回のコードをまとめてみよう。remove-reference に対するメソッドだけ、:around 指定を追加してある。
;; declaration & default method (defgeneric operator= (lhs rhs)) (defmethod operator= (lhs rhs) ; [A] (format t "(operator= T T) called.~%") rhs) ;; move semantics (defclass remove-reference () ()) (defmethod operator= :around (lhs (rhs remove-reference)) ; [B] (format t "(operator= T remove-reference) called.~%") rhs) ;; class foo (defclass foo () ()) (defmethod operator= ((lhs foo) (rhs foo)) ; [C] (format t "(operator= foo foo) called.~%") rhs) ;; class bar (defclass bar () ()) (defmethod operator= ((lhs bar) (rhs bar)) ; [D] (format t "(operator= bar bar) called.~%") rhs)
これで、以下のようなメソッドが追加されても第2パラメータが remove-reference であれば [B] がコールされてくれる。
(defmethod operator= ((lhs foo) rhs) ; [E] (format t "(operator= foo T) called.~%") rhs) * (let ((foo (make-instance 'foo)) (bar (make-instance 'bar)) (rm (make-instance 'remove-reference))) (operator= foo foo) (operator= bar bar) (operator= foo bar) (operator= foo rm) (operator= bar rm) (values)) => (operator= foo foo) called. (operator= bar bar) called. (operator= foo T) called. (operator= T remove-reference) called. (operator= T remove-reference) called.
B がコールされなくなる唯一(だと思うけど)の状況は、以下のように :around 指定でより特定的なメソッドが追加された場合だ。
(defmethod operator= :around ((lhs foo) (rhs remove-reference)) ; [F] (format t "(operator= foo remove-reference) called.~%") rhs)
しかし、これは明らかに意図的なものと言って良いと思う。やりたかったのは [E] のようなものを追加したことによって意図せず move semantics を破壊してしまうことを防ぐことだ。[F] のようなものを禁止することはできないが、さすがにこれは「わかってやってるよね?」と言えると思う。
さて、これでほぼ代入と move semantics について悩むのも終わりだ。ベースになる部分は実装したので、あとは各種のコンテナに関する operator-move を実装することと、随所に存在する「代入」── これは現在無邪気にも setf で実行してしまっているのだが ── を opr= マクロ呼び出しに置き換えること‥‥‥てそれが一番大変なんだけどな。
コメント
このページのタグ
Page tag : Common Lisp
Page tag : STLとその移植
Copyright(C) 2005-2021 project-enigma.
Generated by CL-PREFAB.