Boost.Variant そのさん boost::recursive_wrapper<>

http://d.hatena.ne.jp/janus_wel/20101004/1286201416 までで単純な data structure を構築することができるはず。最後に再帰的な data structure を構成するための utility class を使ってちょっと遊んでみる。

まず前提として型まわりの挙動から。 C++ では再帰的に自分そのものを持つような型を定義することができない。

// Compilers don't pass this codes.
struct A {
    A a;
};

ここらへんは C++0x の仕様書だと 9.2.9 に書いてある。

Non-static data members shall not have incomplete types. In particular, a class C shall not contain a non-static member of class C, but it can contain a pointer or reference to an object of class C.

俺訳 ) 非 static なデータメンバーは不完全型であってはならない。特に、クラス C は非 static なクラス C であるメンバーを含んではならない。しかしクラス C のオブジェクトを指すポインターを含むことはできる。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3126.pdf

というわけで上記の code のようなことをやりたい場合、仕様に書かれているように pointer を使って以下のように書かなければならない。

// OK
struct A {
    A* a;
};

見たことあるような code になった、というかこれ内容を持たない linked list じゃん !! というオチはともかく。まぁこういう制限がある。

ちなみになぜ pointer 型なら OK なのかというは pointer 型は処理系定義ではあるものの固定長というのは決まっているのでその class の size がちゃんと求まるから、じゃないかな。つまり pointer 型じゃない、自分そのものを持つ場合は size がわからないのでダメ、と。仕様をちゃんと追ったわけじゃないけど、というか探したんだけど該当箇所見つからんかったのよね。

さて、できないと言われるとできるようにしたくなるのが性なわけでそんなひとむけに boost::recursive_wrapper<> がある、とまぁこういうハナシ。ああやっと辿りついた。

// OK
struct A {
    boost::recursive_wrapper<A> a;
};

以上のように書くと問題なく compile できて以下のような code も通る。

A x;
x.a = A();

ただまぁ正直これだけだと何がうれしいのかわからないわけなんだけど、というところで長くなったので切る。