boost::scoped_ptrはデストラクタが定義されていないとエラーになるという話がなかなかわかったが、人から説明をうけてやっとわかった。
  • http://twitter.com/SubaruG/status/14747212751
  • http://twitter.com/SubaruG/status/14747268037
  • http://twitter.com/SubaruG/status/14747325492
=== main.cc ===
     1  #include "hoge.h"
     2  int
     3  main()
     4  {
     5      hoge h;
     6  }
=== hoge.h ===
     1  #include <boost/scoped_ptr.hpp>
     2  struct hoge
     3  {
     4      hoge();
     5      ~hoge() {} //もしデストラクタをユーザ定義しないとすると、コンパイラがデフォルトでこんなのを生成する
     6   private:
     7      class impl;
     8      boost::scoped_ptr<impl> pimpl_;
     9  };
=== impl.cc ===
     1  #include "hoge.h"
     2  #include <iostream>
     3  struct hoge::impl
     4  {
     5      impl() { std::cout << "impl+" << std::endl; }
     6      ~impl() { std::cout << "impl-" << std::endl; }
     7  };
     8  hoge::hoge() : pimpl_(new hoge::impl) {}

% c++ -I/usr/local/include -c main.cc
/usr/local/include/boost/checked_delete.hpp: In function 'void boost::checked_delete(T*) [with T = hoge::impl]':
/usr/local/include/boost/smart_ptr/scoped_ptr.hpp:80:   instantiated from 'boost::scoped_ptr::~scoped_ptr() [with T = hoge::impl]'
hoge.h:5:   instantiated from here
/usr/local/include/boost/checked_delete.hpp:32: error: invalid application of 'sizeof' to incomplete type 'hoge::impl'
/usr/local/include/boost/checked_delete.hpp:32: error: creating array with negative size ('-0x00000000000000001')
/usr/local/include/boost/checked_delete.hpp:33: error: invalid application of 'sizeof' to incomplete type 'hoge::impl'
/usr/local/include/boost/checked_delete.hpp:33: error: creating array with negative size ('-0x00000000000000001')
/usr/local/include/boost/checked_delete.hpp:34: warning: possible problem detected in invocation of delete operator:
/usr/local/include/boost/checked_delete.hpp:29: warning: 'x' has incomplete type
hoge.h:7: warning: forward declaration of 'struct hoge::impl'
/usr/local/include/boost/checked_delete.hpp:34: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
*** Error code 1
なぜメンバ変数 piml_ の実体化のところで、その外にあるクラスのデストラクタの有無が影響してくるのかだが、
  1. hoge のデストラクタが定義されてないので main.cc の中でデフォルトで生成される。
  2. よってメンバ変数のpimpl_ のデストラクタを main.cc の中で実体化する必要がある。
  3. よってデストラクタの中で使われている boost::checked_delete<impl>() も実体化される。
  4. だが impl は定義がない不完全型なので sizeof が失敗してエラーになる。