typedefと前方参照
Objective-Cのプログラミングで起きた事件で最近印象深かった件。
Objectice-CではC++と同様に前方参照の機能がある。例えば適当なヘッダファイル内のクラス定義で、
@class T;
@interface A : NSObject {
T* _t;
...
みたいにして、Tの定義が出るより前にコンパイルを通すことができる。これを使うと、ファイルのインクルード順はあんまり気にしなくてもよくなるでたいへん便利である。
しかし問題になるのは、この"T"がクラスではなく、後方でtypedefで定義される場合だ。このときは、Tのtypedefが先に来るようにインクルード順をもってくる以外に手段は存在しない。いろいろ試行錯誤したが失敗した。
ただ、typedefの中身に前方参照が含まれているのは問題ない。
@class T;
typedef T S;
@interface A : NSObject {
S* _t;
これならOKである。でも、Sのtypedefが後方でもう一度出現するのは定義の中身が同一であってもNGである。
さらにやっかいなのは、自分のコードではわりとでかい#defineマクロをグワッと展開するとクラス定義やtypedef一式が生成されるようになっていて、なかなかtypedefだけを先に持ってくることが面倒くさいことだ。こういう事態に備えて、enum系を含むtypedef一式は別ファイルに分離するのがよいのかもしれない。
そして二重に驚きなのは、この制約はC++でも同じであるにもかかわらず、過去この問題で悩んだ記憶がないということだ。typedefはあまり使っていなかったのかもしれないし、この程度のことを面倒だと思う心を持ち合わせていなかったのかもしれない。C++のtemplateは酷使していた記憶があるので一度くらいこれでひっかかってもいいと思うのであるが...
ここ数年、C#やJavaなどの2パス型コンパイラの言語しかいじってなかったのでインクルード順に気を配るようなセンスがまったく失われているぜ。
昔はフルビルドに結構時間がかかるプロジェクトも多かったので、「いろいろなところから#includeされているファイルを修正する」ことに恐怖感があったものだが今はそういうのはないよなあ。
もうファイルを分割するのが面倒なのが先にきて、必要なのはtypedef一個であるにもかかわらずでかいファイルをまるごと#importして「ま、いいか」となっている。
最近のコメント