#include <cassert>
#include "boost/shared_ptr.hpp"
struct Hoge;
struct HogeRegistry { void insert(Hoge*); void erase(Hoge*); };
struct WrappingDeleter
{
HogeRegistry& owner;
boost::shared_ptr<Hoge> original_holder;
WrappingDeleter(HogeRegistry& owner, boost::shared_ptr<Hoge>& inserted)
: owner(owner)
, original_holder(inserted) {}
void operator () (Hoge* raw)
{
assert(raw == original_holder.get());
owner.erase(raw);
}
};
void insert(HogeRegistry& hogeReg, boost::shared_ptr<Hoge>& hoge)
{
Hoge* const raw = hoge.get();
hogeReg.insert(hoge.get());
try
{
boost::shared_ptr<Hoge> const wrapping(raw, WrappingDeleter(hogeReg, hoge));
// wrapping (およびそのコピー)が生きている間はデリータが
// 持っているオリジナルの shared_ptr が生き続ける。
hoge = wrapping;
}
catch (...)
{
hogeReg.erase(hoge.get());
throw;
}
}
#include <iostream>
#include "boost/noncopyable.hpp"
#define LOG(p) (std::cout << __PRETTY_FUNCTION__ << ": " << static_cast<void const*>(p) << std::endl)
struct Hoge : boost::noncopyable
{
Hoge()
{
LOG(this);
}
~Hoge()
{
LOG(this);
}
};
void HogeRegistry::insert(Hoge* p)
{
LOG(p);
}
void HogeRegistry::erase(Hoge* p)
{
LOG(p);
}
int main()
{
HogeRegistry hogeReg;
{
std::cout << "Case NG." << std::endl;
boost::shared_ptr<Hoge> hoge(new Hoge());
hogeReg.insert(hoge.get());
}
{
std::cout << "Case OK." << std::endl;
boost::shared_ptr<Hoge> hoge(new Hoge());
insert(hogeReg, hoge);
}
return 0;
}