void型
当たり前だがvoid型はインスタンスを生成できない。しかしこれ場合によっては困ることがある。例えば以下のような状況
template< class DATA > class Node{ ・・・ private: DATA m_Data; };
クラステンプレートの典型的な例だが、このテンプレート引数にvoidを渡すとインスタンス生成できないのでコンパイルエラーになる。そもそもvoidを渡す状況があるのか?という問題もあるがこれ意外にあったりします。例えばグラフ理論、ノードとエッジには必ずしもデータが乗るとは限らないので、データ不要の場合はvoidを渡すということがありうる。
まあ、クラステンプレートの場合は以下の逃げ方があります。
template< class DATA > class Node{ ・・・ private: DATA m_Data; }; template<> class Node<void>{ ・・・ private: //DATA m_Data; };
特殊化を利用してvoidの場合だけ作り直せばよい。ただしこれ1つ欠点があって、特殊化するのは実際には持っているデータだけなのだがその他の部分も2つ用意しなければいけない。クラスがでかいとかなり煩雑なコードになる。
もう一つの解決方法として、ポインタにしてしまうという手がある。
template< class DATA > class Node{ ・・・ private: DATA* m_pData; };
しかしこれ状況によっては全く意味が無い。中のデータのインスタンスを中で生成する場合、結局voidかどうかで場合分けが必要になる。
void* p = new void; //↑こういう事は出来ない。
まあそんなわけで、たとえアクセス不能であってもよいのでvoid型が生成できる方が嬉しい。
void data; //↑こういうのを認めて欲しい
しかしこれ、関数に関しては若干余裕があるっぽい。
void functA() { ・・・ return void(); } void functB() { return functA(); }
適切なサンプルが思いつかなくてすごく適当なプログラムだが、上記の関数、なんとコンパイルが通るのだ。なお試したのはVC2005(風の噂では古いコンパイラだとOUTらしい)。これは結構助かる。ファンクタを使ったプログラムとか書く場合、戻り値がvoidかどうかで場合分けとかやってたらメチャしんどいので。ていうか最近までvoidを考慮するの忘れてたorz そしたら考慮する必要がなくなっていて嬉しい限りです。
どうでもいいけど一時オブジェクトもOKなのでこんなのも通ったりします。
void( void( void( void( void() ) ) ) );
面白いことに初期化値(?)を取ることも出来ます。
ここまで出来るんだったらクラステンプレートも考慮にいれてvoidインスタン生成もそのうち認められるかも?