boost C++ Libraries(以下単にboost)には、 mplやspiritみたいにやたらと気合の入ったでかいライブラリから、 ちょっとしたことに便利な小さなライブラリまでいろいろあります。 この記事では、細かいライブラリを紹介していこうかと思います。
必要なヘッダー: <boost/checked_delete.hpp>
C++では(Cでもですが)、不完全型(incomplete type)というものがあります。
詳細な説明はここではしませんが、一言で言ってしまえば「宣言だけされて定義がされていない型」
といったところでしょうか。
struct hogehoge { /* ... */ };
のようにクラス(構造体、共用体)の詳細を定義しているのではなく、
struct hogehoge;
のようにクラス名の宣言しかしていないような、アレです。
んで、C++標準ではこの不完全型へのポインタに対して、deleteする操作を認めています。
ところが、当然不完全型ですから、そのクラスのデストラクタやoperator deleteなんて知らないわけです。 C++標準では、デストラクタもoperator deleteもないクラスなら、正しくdeleteされるのですが、 どちらか一方でも存在した場合、deleteする動作は未定義となっています。
では、この未定義の動作は具体的にはどんな動作をするんだろうと思って調べてみると、 警告こそ出ますが、コンパイルには通ってしまいます(VC7.1で確認)。 コンパイラにしてみれば、不完全型なのでそもそもデストラクタなどがあるかどうかなど判らないのです。
そこで、そもそも不完全型のdeleteをできないようにしてしまおう、というのがこのライブラリです。 以下の関数とファンクタから成ります。
001 namespace boost { 002 template<class T> void checked_delete(T* p); 003 template<class T> void checked_array_delete(T* p); 004 template<class T> struct checked_deleter; 005 template<class T> struct checked_array_deleter; 006 }
checked_delete()
関数は、不完全型のチェックをしつつdeleteを行います。
不完全型のチェックはコンパイル時に行われ、不完全型ならエラーを吐くようになっています。
また、コンパイル時にチェックを行うので、inline関数がきちんと展開されれば実行時のオーバーヘッドはありません。
checked_array_delete()
関数は、new[]で確保されたメモリの解放を行います。
checked_(array_)deleter
構造体は、その関数オブジェクト版です。
本来の目的とは違いますが、delete
を行う関数オブジェクトとして使うのもいいかもしれません。
必要なヘッダー: <boost/current_function.hpp>
__FILE__
や__LINE__
と同じようなマクロのシンボルです。
BOOST_CURRENT_FUNCTION
と書けば、現在の関数名に置換されます。
この機能は大抵のコンパイラが独自拡張で実装しているのですが、
コンパイラによってシンボル名がまちまちなので、
これを使うことによって移植性の向上が図れます。
必要なヘッダー: <boost/assert.hpp>
標準の<cassert>と同じように、アサーションを行うためのライブラリです。 プリプロセッサのシンボルを予め定義しておくことによって、
assert
に置換するの3通りの動作を行います。
BOOST_DISABLE_ASSERTS
が定義されている場合、アサーションは全て消去されます。
例によって、BOOST_ASSERT
に副作用のある式を与えていると動作が変わってしまいますので、
副作用のある式は与えないようにしましょう。
BOOST_ENABLE_ASSERT_HANDLER
が定義されている場合、
アサーション失敗時にユーザー定義の関数を呼び出すようになります。
呼び出されるのは、次のような関数です。
001 namespace boost { 002 void assertion_failed(const char* expr, 003 const char* function, 004 const char* file, 005 long line); 006 }
これを、どこか適当なcppファイルで定義しておきましょう。
説明するまでもないかとは思いますが、
expr
はBOOST_ASSERT
に与えた式の文字列表現、
function
はエラーの発生した関数名、
file
はファイル名、line
は行番号です。
以上2つのシンボルがいずれも定義されていない場合は、
ただのassert
に置換されます。