Boost.Variant そのご boost::recursive_wrapper<> の中身
もうちょっとだけ続くんじゃ。
boost::recursive_wrapper<> は言語仕様でできないことをしているわけでどうやって実現してるんだろうという方向へ。というわけで source を覗いてみた。
さぞかしすごいことをーとか思ってたんだけど実際はかなり簡単な仕組みだった。一言でいうと template parameter に指定された型、つまり wrapped type の pointer を内部に持つ class 。そこにいろいろ追加して使い勝手を良くしているだけだった。
- constructor
- default constructor と copy constructor の他に wrapped type object を取る constructor が定義されているので object 構築のときに型を気にすることなく渡すことができる。
- 内部 pointer の指す先として new を使って wrapped type object を作り出している。
- 代入演算子
- wrapped type の object を取るものも定義されているのでこっちも透過的に代入できる。
- destructor
- 内部 pointer が指す object を delete していいかどうかを check してから破棄する。この処理には boost/checked_delete.hpp が使われてる。
- 細かいところ
- 内部に持っている wrapped type object への pointer をそのまま返す get_pointer() と dereference してから返す get() という member function がある。
- assign() と swap() という member function が定義されている。
- wrapped type への型変換をする operator T() 関数は定義されてないみたい。
というわけで本当に wrap してるだけみたい。構築や copy は透過的にできるけど access は get() member function を使え、という方向かな。まぁ access に関しては Boost.Variant で data structure を構築したら visitor pattern を使う、という設計思想みたいなので get() member function を使うのはちょっと違うんだろうけど。
でまぁ object 構築のときに内部 new して wrapped type object を生成する、という性質があるんだけどこれをどうみるか。ひとつの立場として効率が悪そうだからあまり多用したくないというのもあると思うけど recursive_wrapper<> を使わないで自分自身の pointer を member として持つ型を定義した場合、実際の data structure を構築するのにやっぱり自前で new だの delete しなきゃならないのでそこはあまり問題ではないというか。問題になる場合そもそもそういう data structure が向いてないってことになるだけ、だよな。
どちらかというと自分で data の寿命を管理しなくていいわけなので利点の方が多い気がする。まぁ access する際の visitor pattern の適用はどうしても再帰処理になってしまうので深すぎる data structure だと stack overflow してしまうとかの可能性はあるけど。