...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

boost::noncopyable

#include <boost/utility.hpp>
class Class : /*private*/ boost::noncopyable
{
priavte:
  //Class(const Class&);
  //Class& operator=(const Class&);
public:
};
int main()
{
  Class a, b;
  a = b;      // 代入演算子;エラー
  Class c(a); // コピーコンストラクタ;エラー
  return 0;
}

コピーしてはいけないクラスを作りたいとき,上の private 部のように代入演算子とコピーコンストラクタの宣言を記述しておいて,それらの中身を実装しない(関数定義を記述しない)という手法がある.
boost::noncopyable を private 継承(デフォルトで private)すると, boost::noncopyable に書かれた代入演算子とコピーコンストラクタが Class の private 部に継承されるので,いちいち自分で書かなくてもよくなる.

実践

試しに,研究で使ってたソフトウェアの中で,代入演算子とコピーコンストラクタを自分で定義しておらず,ポインタをメンバに持ち,どこでもコピーしていないつもりのクラスに boost::noncopyable を使用してみた.
そしたら,最初のうちは問題なくコンパイルできていたのだが,あるクラスがコンパイルエラーになってしまった.
あ痛たたたたたたた.これはひどい


コードを見てみると,ポインタをコピーしてしまって起こるトラブルに取り組んだような形跡があった.
デストラクタでポインタメンバに NULL を入れたり,そのメンバを各所で ASSERT(member != NULL); してたり.
・・・そういえばずっと前に原因がよくわからないバグがあって困ってたような気が・・・.
コードをよく読み直して,これまでのところ,処理結果には悪影響がなかったことが確かめられた.
怖ええ.